使用grepl和dplyr汇总R中的多个搜索字符串

时间:2015-03-04 12:35:06

标签: r dplyr grepl

我有一个相当无组织的数据框,在一列中有相同类别的不同名称。我想用dplyr总结那些凌乱的名字。

这是一个简化的树种及其特征的数据集:

df <- data.frame(species = c('sp1', 'sp1', 'sp1', 'sp2', 'sp2'), tr = c('leaf nitrogen per mass', 'wood den', 'nitrogen (per mass)', 'leaf carbon per area', 'wood dens'), val = sample(1:10, 5), stringsAsFactors=F)

因此,每个物种在此数据集中都有许多不同类别的特征值。

您可以使用dplyr和以下代码获取每个物种的汇总统计数据。

library(dplyr)
by_sp<- df %>% 
group_by(species, tr)

by_sp %>% summarize(avg = mean(val))

您可以看到它将相同的特征视为单独的特征,因为它们不完全匹配。我想总结一下这些使用模糊匹配的许多不同的特征,但不知道如何在许多特征同时实现这一点。到目前为止,我已经尝试使用grepl创建一个“必需”字符串向量来过滤。实施例

lmass <- 'nitrogen|mass'
by_sp %>% filter(grepl(lmass, tr, ignore.case=T)) %>% summarize(ave = mean(val))

但这是使用'或',而我想'和' - 需要两个字符串,以便最终的数据帧是包含氮和质量的所有行的单个平均值(在列tr中)。

此外,我有很多这些特征字符串,我想要一个最终的数据帧,每个物种的每个特征的平均值。到目前为止,我已尝试组合不同的搜索字符串,但这不起作用。

wood <- 'wood den' #this could have other keywords required for this trait
alltr <- c(lmass, wood)
leaf_tr %>% filter(grepl(alltr, tr, ignore.case=T)) %>% summarize(ave = mean(val)) #gives an error, only takes first element in alltr

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

这是一个data.table解决方案。我知道您要求dplyr,但遗憾的是,我遇到的一些问题超出了我的dplyr技能(例如,使用mutate创建了多个列):

# setup regular expressions, etc.

library(data.table); library(reshape2)    
traits <- c(nm="nitrogen.*mass", wd="wood den", ca="carbon.*area")
trait.nm <- names(traits)
DT <- data.table(df)  # make data table

DT[,  # Add a column for each trait, indicating whether row matches the trait
  c(trait.nm):=
    data.frame(sapply(trait.nm, function(x) grepl(traits[x], tr)))
]    
melt(DT, id.vars=names(df))[           # transform to long format
  value == TRUE,                       # filter for trait-val combinations that match  
  sum(val), by=.(species, variable)    # group by standardized trait
]

这会产生:

   species variable V1
1:     sp1       nm 13
2:     sp1       wd  3
3:     sp2       wd  1
4:     sp2       ca  2

注意我添加了“碳区”类别。为了解决氮质量的“OR”问题,我只是将正则表达式更改为"nitrogen.*mass"

有一点需要注意的是,你需要确保每个特征只能匹配一个正则表达式,否则你最终会在不同的特质类别中多次计算特征。