我有一个相当无组织的数据框,在一列中有相同类别的不同名称。我想用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
非常感谢任何帮助!
答案 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"
。
有一点需要注意的是,你需要确保每个特征只能匹配一个正则表达式,否则你最终会在不同的特质类别中多次计算特征。