问题 基于特定因子组合对行进行求和


这可能是一个愚蠢的问题,但我已经阅读了克劳利关于数据框架的章节并浏览了互联网并且还没有能够做任何工作。

这是一个类似于我的示例数据集:

> data<-data.frame(site=c("A","A","A","A","B","B"), plant=c("buttercup","buttercup",
"buttercup","rose","buttercup","rose"), treatment=c(1,1,2,1,1,1), 
plant_numb=c(1,1,2,1,1,2), fruits=c(1,2,1,4,3,2),seeds=c(45,67,32,43,13,25))
> data
  site     plant treatment plant_numb fruits seeds
1    A buttercup         1          1      1    45
2    A buttercup         1          1      2    67
3    A buttercup         2          2      1    32
4    A      rose         1          1      4    43
5    B buttercup         1          1      3    13
6    B      rose         1          2      2    25  

我想要做的是创建一个场景,只要存在独特的site&plant&treatment&plant_numb组合,就会将“种子”和“水果”相加。理想情况下,这会导致行减少,但保留原始列(即我需要上面的示例看起来像这样:)

  site     plant treatment plant_numb fruits seeds
1    A buttercup         1          1      3   112
2    A buttercup         2          2      1    32
3    A      rose         1          1      4    43
4    B buttercup         1          1      3    13
5    B      rose         1          2      2    25

这个例子非常基本(我的数据集是~5000行),虽然在这里你只看到两行需要求和,需要求和的行数各不相同,范围从1到45。

到目前为止,我已经尝试过rowum()和tapply(),结果非常糟糕(错误告诉我这些函数对于因素没有意义),所以如果你能指出我正确的方向,我会非常感激!

非常感谢!


10616
2018-05-03 03:16


起源

看着那(这 plyr 和 data.table 标签。很多问题基本上都解决了这个问题。祝你好运! - Chase
也可以看看 4dpiecharts.com/2011/12/16/... - Richie Cotton


答案:


希望以下代码是相当不言自明的。它使用基本功能“聚合”,基本上这是说站点,植物,处理和plant_num的每个独特组合看果实和种子总和的总和。

# Load your data
data <- data.frame(site=c("A","A","A","A","B","B"), plant=c("buttercup","buttercup",
"buttercup","rose","buttercup","rose"), treatment=c(1,1,2,1,1,1), 
plant_numb=c(1,1,2,1,1,2), fruits=c(1,2,1,4,3,2),seeds=c(45,67,32,43,13,25)) 

# Summarize your data
aggregate(cbind(fruits, seeds) ~ 
      site + plant + treatment + plant_numb, 
      sum, 
      data = data)
#  site     plant treatment plant_numb fruits seeds
#1    A buttercup         1          1      3   112
#2    B buttercup         1          1      3    13
#3    A      rose         1          1      4    43
#4    B      rose         1          2      2    25
#5    A buttercup         2          2      1    32

行的顺序改变(并按站点,工厂......排序),但希望这不是太多的问题。

另一种方法是使用plyr包中的ddply。

library(plyr)
ddply(data, .(site, plant, treatment, plant_numb), 
      summarize, 
      fruits = sum(fruits), 
      seeds = sum(seeds))
#  site     plant treatment plant_numb fruits seeds
#1    A buttercup         1          1      3   112
#2    A buttercup         2          2      1    32
#3    A      rose         1          1      4    43
#4    B buttercup         1          1      3    13
#5    B      rose         1          2      2    25

11
2018-05-03 03:45



太棒了 - 在我提出这个问题之后,我只是在玩聚合物,但你已经大大加快了我的速度。谢谢你的帮助。还有一个问题:当我输入您显示的代码时,我收到错误“as.data.frame.default(x)中的错误:无法将类”公式“强制转换为data.frame”。有关使它工作的任何想法? - user1371443
不幸的是,两者都是。我为示例和我的实际数据集(没有空格)得到相同的错误消息:> aggregate(cbind(fruits,seeds)~site + plant + treatment + plant_numb,sum,data = data)错误as。 data.frame.default(x):不能将类“公式”强制转换为data.frame - user1371443
plyr解决方案应该仍然可以工作我猜。但听起来你没有聚合的公式版本。您使用的是哪个版本的R?我认为聚合已经允许从2.11开始输入公式 - Dason
哈!就是这样 - 我的R版本很古老。非常感谢!!! - user1371443


为了完整起见,这里是 data.table 解决方案,正如@Chase所建议的那样。对于较大的数据集,这可能是最快的方法:

library(data.table)
data.dt <- data.table(data)
setkey(data.dt, site)
data.dt[, lapply(.SD, sum), by = list(site, plant, treatment, plant_numb)]

     site     plant treatment plant_numb fruits seeds
[1,]    A buttercup         1          1      3   112
[2,]    A buttercup         2          2      1    32
[3,]    A      rose         1          1      4    43
[4,]    B buttercup         1          1      3    13
[5,]    B      rose         1          2      2    25

lapply(.SD, sum) part总结了所有不属于分组集的列(即不在列中的列) by 功能)


4
2018-05-03 04:33