【问题标题】:Split text in columns of data frame based upon part of a pattern根据部分模式拆分数据框列中的文本
【发布时间】:2017-08-03 15:07:05
【问题描述】:

使用 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) 删除第一个数字,如果可以使用 \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))) 确实允许我只拆分为 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)

【问题讨论】:

  • 正如here 所讨论的,来自tidyrextract 可能会提供必要的灵活性。
  • @Konrad 虽然这确实是可能的(例如tidyr::extract(data=repdf,a,into=c('tax','prob'),"(.*)\\((?=\\d)(.*)",perl=TRUE),但推断具有多列的 data.frame 并不容易。
  • @Konrad:你让我思考。虽然我最初卡在tidyr::extract 的非标准评估版本上,但标准评估功能实际上非常优雅。我在下面添加了一个使用它的答案。

标签: r strsplit


【解决方案1】:

这就是前瞻派上用场的地方...本质上,我们寻找(,后跟一个数字\\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)"

【讨论】:

    【解决方案2】:

    受@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),这对于下游数据整理很有用。 另一方面,关于已接受答案的有趣之处在于,当事先不知道数据拆分到的列数(或取决于初始数据框列的变量)时,它仍然会像魅力一样工作。

    【讨论】:

      猜你喜欢
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      相关资源
      最近更新 更多