【问题标题】:Summarizing across multiple search strings in R using grepl and dplyr使用 grepl 和 dplyr 汇总 R 中的多个搜索字符串
【发布时间】:2015-05-05 10:53:09
【问题描述】:

我有一个相当杂乱无章的数据框,其中一列中相同类别的名称各不相同。我想用 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

任何帮助将不胜感激!

【问题讨论】:

    标签: r dplyr grepl


    【解决方案1】:

    这是一个 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"

    对此的一个重要警告是,您需要确保每个特征只能匹配一个正则表达式,否则您最终会在不同的特征类别中多次计算该特征。

    【讨论】:

    • 谢谢布罗迪-我绝对同意你的警告。这就是我需要这种多字符串匹配的全部原因。我在尝试实现您的代码时遇到了一些问题。首先,我尝试更改正则表达式并在 dplyr 中使用它,使用“nitrogen.*mass”,但它仍然不能在“每质量叶氮”和“每质量氮”类别中平均。对我来说似乎很奇怪,它可以与 data.table 一起使用,但不能与 dplyr 一起使用。
    • 另外,我认为“。”可能有问题。在熔体指数中。我的运行抛出了一个错误,但如果你将 'by=.()' 更改为 'by=list()' 它就会运行。
    • @by=.() 是在较新版本的数据表中实现的,所以这可能是您遇到的问题。它是list()的别名
    • 太好了,更新了,它可以工作了!我仍然想将它保留在 dplyr 中,因为我需要运行其他代码,这些代码对于该包来说非常直观,但很高兴有这个选项。
    猜你喜欢
    • 2017-03-30
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 2016-06-03
    • 2021-07-14
    • 1970-01-01
    • 2014-12-02
    • 2014-12-01
    相关资源
    最近更新 更多