我正在尝试将R中的数据从长格式整形为宽格式。我想同时通过ID获得类型变量的出现次数和通过ID获得第二个变量(val
)的值的总和并按照下面的示例进行输入。
我能够找到用整形或整形进行重塑的答案,但不能同时使用这两种方法。
这是原始示例数据:
> df <- data.frame(id = c(1, 1, 1, 2, 2, 2),
+ type = c("A", "A", "B", "A", "B", "C"),
+ val = c(0, 1, 2, 0, 0, 4))
> df
id type val
1 1 A 0
2 1 A 1
3 1 B 2
4 2 A 0
5 2 B 0
6 2 C 4
我想获得的输出如下:
id A.count B.count C.count A.sum B.sum C.sum
1 1 2 1 0 1 2 0
2 2 1 1 1 0 0 4
其中count
列显示类型A,B和C的出现次数,而sum
列按类型显示值的总和。
要实现计数,我可以按照this answer中的建议,将reshape2::dcast
与默认聚合功能length
结合使用:
> require(reshape2)
> df.c <- dcast(df, id ~ type, value.var = "type", fun.aggregate = length)
> df.c
id A B C
1 1 2 1 0
2 2 1 1 1
类似地,如this answer中所建议,我也可以使用总和作为输出来执行整形,这次使用sum
中的dcast
聚合函数:
> df.s <- dcast(df, id ~ type, value.var = "val", fun.aggregate = sum)
> df.s
id A B C
1 1 1 2 0
2 2 0 0 4
我可以将两者合并:
> merge(x = df.c, y = df.s, by = "id", all = TRUE)
id A.x B.x C.x A.y B.y C.y
1 1 2 1 0 1 2 0
2 2 1 1 1 0 0 4
但是有一种方法可以一次性完成所有操作(不一定使用dcast
或reshape2
)吗?
答案 0 :(得分:5)
从data.table v1.9.6开始,可以转换多个value.var列,还可以通过提供多个fun.aggregate函数进行转换。见下文:
library(data.table)
df <- data.table(df)
dcast(df, id ~ type, fun = list(length, sum), value.var = c("val"))
id val_length_A val_length_B val_length_C val_sum_A val_sum_B val_sum_C
1: 1 2 1 0 1 2 0
2: 2 1 1 1 0 0 4
答案 1 :(得分:1)
建议的data.table
解决方案可能会更好,但是如果您更喜欢使用dcast
并且有很多value.var
/ fun.aggregate
组合,也可以这样做:
library(purrr)
cols <- c('type', 'val')
funs <- c(length, sum)
map2(cols, funs, ~ dcast(df, id~type, value.var = .x, fun.aggregate = .y)) %>%
reduce(left_join, by='id', suffix=c('.count', '.sum'))
答案 2 :(得分:1)
这是使用tidyverse
library(tidyverse)
df %>%
group_by(id, type) %>%
summarise(count = n(), Sum = sum(val)) %>%
gather(key, val, count:Sum) %>%
unite(typen, type, key, sep=".") %>%
spread(typen, val, fill = 0)