1

我有类似这样的数据:

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 家医院和 4 个等级的因子得分(0、1、2、3)。一些医院没有对特定分数水平的观察

我想生成一个新的数据框,其中变量 Var1、Var2 和 Var3 相加。所以使用上面的数据会给出

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

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

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

4

3 回答 3

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.frameformula

更新

您在使用 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
于 2012-10-12T10:54:18.500 回答
3

data.table内存、编码和时间效率的解决方案。

鉴于您习惯于使用SQLdata.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]

但是,当您不需要时,为什么要编写所有这些额外的代码!

于 2012-10-16T05:27:04.480 回答
1

以 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基于 的colwise内部调用strip_splits又删除了那些用于执行拆分的列,即Hosp在这种情况下。上一句中的所有函数都来自plyr.

于 2012-10-12T11:43:21.740 回答