我有以下数据:
test <- data.frame(Var1 = factor(c("A", "B", "A", "A", "B")),
Var2 = factor(c("I", "II", "II", "I", "III")),
x = c(1,1,2,3,4)
)
我想分别为每个变量的每个级别得到x
的总和。 Aggregate不能满足我的需求:
>aggregate(test$x, by=list("Var1"= test$Var1,"Var2" = test$Var2), sum)
Var1 Var2 x
1 A I 4
2 A II 2
3 B II 1
4 B III 4
我希望它如下:
Var1-A 6
Var1-B 5
Var2-I 4
Var2-II 3
Var2-III 4
换句话说,它是每个变量的循环,然后是每个变量的级别。
如何在没有循环的情况下执行此操作?我认为reshape
是有序的,但我不知道该怎么做。
答案 0 :(得分:1)
这是有效的(带有警告信息,因为具有不同级别的因素被收集到一个列中):
test %>%
gather(level1, level2, -x) %>%
group_by(level1, level2) %>%
summarise(sum(x))
结果:
level1 level2 `sum(x)`
<chr> <chr> <dbl>
1 Var1 A 6
2 Var1 B 5
3 Var2 I 4
4 Var2 II 3
5 Var2 III 4
因子级别问题in this answer已得到修复。
答案 1 :(得分:1)
OP希望分别计算每个变量的聚合,但希望将单独的结果合并到一个数据框中。在UNION
中,后一步将对应于data.table
操作。
使用rbindlist()
,可以通过library(data.table)
setDT(test)
cols <- c("Var1", "Var2")
rbindlist(
lapply(cols, function(.col) test[, sum(x), by = .col]), idcol = TRUE
)[, setnames(.SD, c("var", "lvl", "sum_x"))][, var := factor(var, labels = cols)][]
# var lvl sum_x
#1: Var1 A 6
#2: Var1 B 5
#3: Var2 I 4
#4: Var2 II 3
#5: Var2 III 4
:
cols
<强>解释强>
lapply()
。rbindlist
循环变量,并为每个变量计算按变量中的级别分组的聚合。结果是data.tables列表。setNames()
按列顺序组合列表。 id列给出了从中获取行的列表元素的编号。注意,我们可以在调用rbindlist()
之前用melt(setDT(test), "x", value.name = "level")[, .(sum_x = sum(x)), by = .(variable, level)]
# variable level sum_x
#1: Var1 A 6
#2: Var1 B 5
#3: Var2 I 4
#4: Var2 II 3
#5: Var2 III 4
命名变量名称的列表元素,但这会因复制结果而导致性能损失。相反,这是在最后一步中完成的,其中只需要将因子标签分配给id列中的数字。
当然,还有一种替代方法(类似于Contacts.CONTENT_FILTER_URI),它首先将数据从宽格式转换为长格式,然后根据变量和级别对聚合进行分组。
data.table
{{1}}报告没有因子级别的问题。
在内存消耗和大问题的速度方面,看看这两种方法中的哪一种更有效是很有趣的。