R 基于模式的一部分在数据框的列中拆分文本

R 基于模式的一部分在数据框的列中拆分文本,r,strsplit,R,Strsplit,使用R,我试图将具有指定分隔符的列中的文本拆分为两个新列。示例数据框如下所示: repdf <- data.frame(a=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)"),b=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)")) 我尝试过使用splitstackshape::cSplit和stringr::str_split_fixed但没有效果。 cSplit(repdf,c(“a”、“

使用R,我试图将具有指定分隔符的列中的文本拆分为两个新列。示例数据框如下所示:

repdf <- data.frame(a=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)"),b=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)"))
我尝试过使用
splitstackshape::cSplit
stringr::str_split_fixed
但没有效果。
cSplit(repdf,c(“a”、“b”),“(”)
在每个“(”)处拆分

cSplit(repdf,c(“a”,“b”),“\\([0-9])”,fixed=FALSE)
删除第一个数字,如果可以使用
\1
将捕获添加到第二个组中,这会很好,但遗憾的是它不是

       a_1 a_2     b_1 b_2
1:     abc 00)     abc 00)
2:     def  5)     def  5)
3:     ghi 00)     ghi 00)
4: j_(klm) 00) j_(klm) 00)
as.data.frame(lapply(repdf,function(x)str_split_fixed(x,“\\(”,n=2))
确实允许我只拆分两列,但当然只需要第一个匹配:

  a.1       a.2 b.1       b.2
1 abc      100) abc      100)
2 def       95) def       95)
3 ghi      100) ghi      100)
4  j_ klm)(100)  j_ klm)(100)

这就是前瞻派上用场的地方……本质上,我们寻找的是
后面跟一个数字
\\d
),但前瞻并不使用数字进行拆分

do.call(cbind, lapply(repdf, function(x){
  do.call(rbind, strsplit(as.character(x), "\\((?=\\d)", perl = TRUE))
}))

# [,1]      [,2]   [,3]      [,4]  
# [1,] "abc"     "100)" "abc"     "100)"
# [2,] "def"     "95)"  "def"     "95)" 
# [3,] "ghi"     "100)" "ghi"     "100)"
# [4,] "j_(klm)" "100)" "j_(klm)" "100)"

受@Konrad建议的启发,我发现以下内容可用于
tidyr::extract
,但我需要使用其“标准评估版本”
tidyr::extract

do.call(cbind, lapply(seq_along(repdf),
       function(df, i){
         tidyr::extract_(data=df[i], col = names(df[i]),
                  into=c(paste0("tax",i),paste0("prob",i)),
                  regex = "(.*)\\((?=\\d)(.*)",perl=TRUE)}, df=repdf))
此处的优点是,您可以为拆分的列提供预定义的名称(例如,此处
tax
prob
),这对于下游数据争用非常有用。
另一方面,关于公认答案的有趣之处在于,当数据被拆分成的列数事先未知时(或取决于初始数据帧列的变量),它仍然会像一个符咒一样工作。

如前所述,
extract
from可能会提供必要的灵活性。@Konrad,尽管这确实是可能的(例如
tidyr::extract(data=repdf,a,into=c('tax','prob'),“(.*)\(?=\\d)(.*”,perl=TRUE)
推断出一个包含多列的data.frame并不是那么容易。@Konrad:你让我思考了一下。当我最初被困在
tidyr::extract
的非标准求值版本时,标准求值函数实际上运行得非常优雅。我在下面添加了一个使用它的答案。
do.call(cbind, lapply(repdf, function(x){
  do.call(rbind, strsplit(as.character(x), "\\((?=\\d)", perl = TRUE))
}))

# [,1]      [,2]   [,3]      [,4]  
# [1,] "abc"     "100)" "abc"     "100)"
# [2,] "def"     "95)"  "def"     "95)" 
# [3,] "ghi"     "100)" "ghi"     "100)"
# [4,] "j_(klm)" "100)" "j_(klm)" "100)"
do.call(cbind, lapply(seq_along(repdf),
       function(df, i){
         tidyr::extract_(data=df[i], col = names(df[i]),
                  into=c(paste0("tax",i),paste0("prob",i)),
                  regex = "(.*)\\((?=\\d)(.*)",perl=TRUE)}, df=repdf))