根据分隔符从字符串中提取数字

时间:2017-01-13 19:16:20

标签: r regex substr

我有以下数据框:

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行),因此效率是一个因素。

感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

我们可以使用sub来匹配字符串的开头(_)后面的非[^_]*^)的zeor或更多字符下划线(_),然后是另一组不是下划线后跟下划线的字符,捕获组中跟随的一个或多个数字((\\d+)),后跟下划线和其他字符,然后替换它与该组的反向引用,最后将其转换为numeric

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

答案 1 :(得分:1)

创建一个my_split函数,找到&#34; _&#34;的开始和结束位置。使用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)