使用apply从数据框中提取括号内容

时间:2018-02-24 20:53:34

标签: r regex apply

我想只提取括号内的内容,如果我使用向量(下面的例子),这种方法效果很好:

j<-"[8] Q(+.98)"
gsub("[\\(\\)]", "", regmatches(j, gregexpr("\\(.*?\\)", j))[[1]])

现在我想使用apply在数据帧的多个列中运行上面的代码。以下是我所做的不起作用。

a<-c("[7] C(+57.02)",  "[11] C(+57.02)",  NA, NA)
b<- c("[16] C(+57.02)",   NA, NA,NA)
c<-c("[9] Q(+.98)" ,   "[13] Q(+.98)" , "[14] C(+57.02)",NA)
abc<-as.data.frame(rbind(a,b,c))

abc_in<-apply(abc, 2, function(x) 
  gsub("[\\(\\)]", "", regmatches(x, gregexpr("\\(.*?\\)", x))[[1]]))

3 个答案:

答案 0 :(得分:2)

您不需要apply()或任何套餐。由于我们在整个数据框架上运行,我们可以先将其强制转换为矩阵,然后使用sub()

sub(".*\\((.+)\\).*", "\\1", as.matrix(abc))
#   V1       V2       V3       V4
# a "+57.02" "+57.02" NA       NA
# b "+57.02" NA       NA       NA
# c "+.98"   "+.98"   "+57.02" NA

这会给你一个矩阵。如果需要保留数据框结构,那么

abc[] <- sub(".*\\((.+)\\).*", "\\1", as.matrix(abc))

当然,您可以循环数据框列。但是为此,我会使用lapply()而不是apply(),因为数据框是一个列表。

abc[] <- lapply(abc, sub, pattern = ".*\\((.+)\\).*", replacement = "\\1")

强制是由sub()隐式完成的,所以从因素开始不是问题。

答案 1 :(得分:1)

它按照你告诉他的方式执行,即只为每列的regmatches列表中的第一个元素。我建议使用来自stringr包的str_extract,它会给出一个向量作为结果,并且更容易编写和使用:

library(stringr)
abs_in <- apply(abc,2,function(x){ gsub("[\\(\\)]", "",str_extract(x,"\\(.*?\\)"))})
> abs_in
     V1       V2       V3       V4
[1,] "+57.02" "+57.02" NA       NA
[2,] "+57.02" NA       NA       NA
[3,] "+.98"   "+.98"   "+57.02" NA    

答案 2 :(得分:0)

另外,使用stringr时,您需要在绑定数据帧时指定stringsAsFactors = FALSE

abc<-as.data.frame(rbind(a,b,c), stringsAsFactors = FALSE)

library(stringr)
regex <- "\\(([^()]+)\\)"
str_match_all(abc, regex)

这会产生

[[1]]
     [,1]       [,2]    
[1,] "(+57.02)" "+57.02"
[2,] "(+57.02)" "+57.02"
[3,] "(+.98)"   "+.98"  

[[2]]
     [,1]       [,2]    
[1,] "(+57.02)" "+57.02"
[2,] "(+.98)"   "+.98"  

[[3]]
     [,1]       [,2]    
[1,] "(+57.02)" "+57.02"

[[4]]
     [,1]           [,2]        
[1,] "(NA, NA, NA)" "NA, NA, NA"

总是选择第二组。