按R中的变量和级别汇总

时间:2017-03-06 23:56:57

标签: r

我有以下数据:

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是有序的,但我不知道该怎么做。

2 个答案:

答案 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

<强>解释

  1. 将变量名称存储在lapply()
  2. 中循环
  3. 使用rbindlist循环变量,并为每个变量计算按变量中的级别分组的聚合。结果是data.tables列表。
  4. 使用setNames()按列顺序组合列表。 id列给出了从中获取行的列表元素的编号。
  5. 重命名列。
  6. 将id列中的数字转换为变量的名称。
  7. 注意,我们可以在调用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}}报告没有因子级别的问题。

    在内存消耗和问题的速度方面,看看这两种方法中的哪一种更有效是很有趣的。