根据模式的一部分拆分数据框列中的文本

Split text in columns of data frame based upon part of a pattern

使用 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)"))

简而言之,我想在每个开括号“(”处拆分,但前提是它后面跟着一个数字,但不会丢失数字。即所需的结果应该如下所示:

a1      a2    b1      b2
abc     100)  abc     100)
def     95)   def     95)
ghi     100)  ghi     100)
j_(klm) 100)  j_(klm) 100)

我曾尝试使用 splitstackshape::cSplitstringr::str_split_fixed 但无济于事。 cSplit(repdf,c("a","b"),"(") 在每个 "("

   a_1  a_2  a_3 b_1  b_2  b_3
1: abc 100)   NA abc 100)   NA
2: def  95)   NA def  95)   NA
3: ghi 100)   NA ghi 100)   NA
4:  j_ klm) 100)  j_ klm) 100)

cSplit(repdf,c("a","b"),"\(([0-9])",fixed=FALSE) 删除第一个数字,如果可以使用 </code> 将捕获添加到第二组那会很好,但遗憾的是它不是。</p> <pre><code> 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))) 确实允许我只分成 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))

这里的优点是您可以为拆分的列提供预定义的名称(例如这里的 taxprob),这对下游数据整理很有用。 另一方面,关于已接受答案的有趣之处在于,当事先不知道数据被拆分成的列数(或变量取决于初始数据框列)时,它仍然会像一个魅力一样工作。