2017-01-13 85 views
0

我有以下数据框:从字符串中提取数字基础上的分隔符

a <- seq(1:5) 
b <- c("abc_a_123456_defghij_1", "abc_a_78912_abc_2", "abc_a_345678912_xyzabc_3", 
          "abc_b_34567_defgh_4", "abc_c_891234556778_ijklmnop_5") 
df <- data.frame(a, b) 
df$b <- as.character(df$b) 

,我需要提取DF $ B而来的第二个和第三个下划线的数量和分配给DF $ C。

我猜这是一个相当简单的解决方案,但还没有找到它。实际的数据集相当大(3MM行),因此效率是一个因素。

感谢您的帮助!

+0

为什么要给我们'a'?似乎只有'b'才能解决这个问题,不是吗? –

+0

你是对的,一个是没有必要的,对不起, – Michael

+2

好像'sub(“。* _(\\ d +)_。*”,“\\ 1”,b)'可能工作。 –

回答

1

创建一个my_split函数,该函数使用gregexpr来查找“_”的开始和结束位置。然后使用substr提取开始位置和结束位置之间的字符串。

my_split <- function(x, start, end){ 
    a1 <- gregexpr("_", x) 
    substr(x, a1[[1]][start]+1, a1[[1]][end]-1) 
} 

b <- c("abc_a_123456_defghij_1", "abc_a_78912_abc_2", "abc_a_345678912_xyzabc_3", "abc_b_34567_defgh_4", "abc_c_891234556778_ijklmnop_5") 

sapply(b, my_split, start = 2, end = 3) 
# abc_a_123456_defghij_1    abc_a_78912_abc_2 
# "123456"      "78912" 
# abc_a_345678912_xyzabc_3   abc_b_34567_defgh_4 
# "345678912"      "34567" 
# abc_c_891234556778_ijklmnop_5 
# "891234556778" 

使用data.table库

library(data.table) 
setDT(df)[, c := lapply(b, my_split, start = 2, end = 3)] 
df 
# a        b   c 
# 1: 1  abc_a_123456_defghij_1  123456 
# 2: 2    abc_a_78912_abc_2  78912 
# 3: 3  abc_a_345678912_xyzabc_3 345678912 
# 4: 4   abc_b_34567_defgh_4  34567 
# 5: 5 abc_c_891234556778_ijklmnop_5 891234556778 

数据:

a <- seq(1:5) 
b <- c("abc_a_123456_defghij_1", "abc_a_78912_abc_2", "abc_a_345678912_xyzabc_3", "abc_b_34567_defgh_4", "abc_c_891234556778_ijklmnop_5") 
df <- data.frame(a, b, stringsAsFactors = FALSE) 
+0

你可以玩弄开始和结束值 – Sathish

4

我们可以用sub到不是一个_[^_]*)的zeor或多个字符从一开始匹配(^)后跟一个下划线(_),然后另一组字符不是下划线foll用下划线义举,捕捉其次是下划线和其他字符组((\\d+))在随后更多的数字的一个,然后用逆向引用该组取代它,并最终将其转换为numeric

as.numeric(sub("^[^_]*_[^_]+_(\\d+)_.*", "\\1", df$b)) 
#[1]  123456  78912 345678912  34567 891234556778