根据变量的值生成数据总和

时间:2012-10-12 10:48:26

标签: r aggregate

我的数据类似于:

Hosp    Score   Var1    Var2    Var3
1       0       5       3       0
1       1       10      8       1
1       2       11      8       2
1       3       5       3       2
2       0       6       4       0
2       2       10      6       1
2       3       10      7       2
3       1       4       3       2
etc...

有大约800个Hosps和4个级别的因子得分(0,1,2,3)。有些Hosps没有观察特定的得分水平

我想生成一个新的数据框,其中变量Var1,Var2和Var3相加。因此,使用上面的数据可以得到

Hosp    Var1    Var2    Var3
1       32      22      5
2       26      17      3
3       4       3       2

这在SQL中是微不足道的(我猜它也在R中!)但是我到目前为止找到的唯一方法是使用循环,每次Hosp更改时都会添加一个新行,并且当它变为n时会增加变量不要改变(当然数据是按照Hosp排序的)。

有没有灵巧的方法来做到这一点?

3 个答案:

答案 0 :(得分:4)

使用aggregate()。假设您的data.frame被命名为“temp”,请使用:

aggregate(list(Var1 = temp$Var1, Var2 = temp$Var2, Var3 = temp$Var3), 
          list(Hosp = temp$Hosp), sum)
#   Hosp Var1 Var2 Var3
# 1    1   31   22    5
# 2    2   26   17    3
# 3    3    4    3    2

slick方式执行此操作,请使用aggregate()的公式表示法:

aggregate(cbind(Var1, Var2, Var3) ~ Hosp, temp, sum)

但请注意,使用默认NA方法和data.frame方法处理formula值的方式不同。

更新

您在原始问题中使用SQL提到过。我没有太多的SQL经验,但也有sqldf包,您可以使用它来执行以下操作:

sqldf("select Hosp, 
      sum(Var1) `Var1`, sum(Var2) `Var2`, sum(Var3) `Var3` 
      from temp 
      group by Hosp")
#   Hosp Var1 Var2 Var3
# 1    1   31   22    5
# 2    2   26   17    3
# 3    3    4    3    2

答案 1 :(得分:3)

用于记忆,编码和时间效率的data.table解决方案。

鉴于您习惯使用SQL,一旦查看了data.table的插图,就应该直截了当地找到data.table的语法。

# assuming your data is in DF
library(data.table)
DT <- data.table(DF)

DT[, lapply(.SD, sum), by = hosp, .SDcols = c('Var1', 'Var2', 'Var3')]

在这种情况下,您可以使用简写lapply(.SD, FUN),将.SDcols设置为运行lapply的变量。

更详细,但SQL - 类似的方法可以产生相同的结果

DT[, list(Var1 = sum(Var1), Var2 =sum(Var2), Var3 = sum(Var3)), by = hosp]

但是为什么你不需要写这些额外的代码呢?

答案 2 :(得分:1)

solution by mrdwab为基础,但提供更短的语法:

aggregate(temp[3:5], temp[1], sum)

这使用数据帧是列表的事实,因此单括号子集将生成具有列子集的数据帧。这样可以避免所有list次呼叫。


另一种选择:

library(plyr)
ddply(temp[-2], .(Hosp), colSums, na.rm = TRUE)

这会将数据框拆分为Hosp的块,并按照colSums(chunk, na.rm = TRUE)的方式计算每个这样的块的列总和。 [-2]会从输入中删除Score列,因此您无法获得总和。

唉,正如mrdwab在下面的评论中正确指出的那样,上面的内容也是Hosp列的总和。我对问题的第一个解决方法如下:

ddply(t[-2], .(Hosp), function(d){colSums(d[-1], na.rm = TRUE)})

这会将Hosp列从参数中删除到colSums,这样它就不会覆盖ddply默认提供的该名称的原始列。总的来说,不再是一个漂亮的解决方案,也不是一个快速的解决方案。但是因为它确实具有明确说明的块上运行的功能,所以它非常灵活,所以我将留待它参考。

在另一条评论中,mrdwab提出了一个更好的解决方案:

ddply(temp[-2], .(Hosp), numcolwise(sum))

这很有效,因为基于numcolwise的{​​{1}}会在内部调用colwise,后者会删除那些用于执行拆分的列,即strip_splits在这种情况下。上一句中的所有函数都来自Hosp