data.table生成多列并汇总
data.table generate multiple columns and summarize them
我正在努力学习 data.table 语法。我掌握了简单摘要的大部分基础知识,但我不知道如何使用 data.table 从现有列生成新列并进行摘要。
这是一个 MWE 示例,我使用 dplyr 和 base 工具从一列创建多列,然后通过分组变量进行汇总:
当前输入
## fact1 fact2 X0
## 1 b 2 9
## 2 a 2 6
## 3 b 1 7
## 4 c 2 3
## 5 a 1 8
## 6 a 1 4
## 7 a 1 5
## 8 a 1 1
## 9 b 1 2
## 10 b 2 10
Base + dlyr 代码
set.seed(10)
dat <- data.frame(
fact1 = factor(sample(c('a', 'b', 'c'), 10, TRUE)),
fact2 = factor(sample(1:2, 10, TRUE)),
X0 = sample(1:10, 10)
)
add <- function(x, y) x + y
z <- sample(1:10, 6, FALSE)
library(dplyr)
z %>%
lapply(., add, dat[, 'X0']) %>%
do.call(cbind, .) %>%
cbind(dat, .) %>%
data.frame() %>%
group_by(fact1, fact2) %>%
summarise_each(funs(sum))
期望输出
## Source: local data frame [5 x 9]
## Groups: fact1
##
## fact1 fact2 X0 X1 X2 X3 X4 X5 X6
## 1 a 1 18 42 22 26 46 30 34
## 2 a 2 6 12 7 8 13 9 10
## 3 b 1 9 21 11 13 23 15 17
## 4 b 2 19 31 21 23 33 25 27
## 5 c 2 3 9 4 5 10 6 7
虽然我要求 data.table 具体解决方案,但我认为看到 base 和 dplyr 等聪明的解决方案可能会使这个问题吸引更广泛的 reader。
可能有更好的方法
library(data.table)
setDT(dat)[, paste0("X", 1:6):= lapply(z, add, X0),
][, lapply(.SD, sum), by = .(fact1, fact2)]
# fact1 fact2 X0 X1 X2 X3 X4 X5 X6
# 1: b 2 19 31 21 23 33 25 27
# 2: a 2 6 12 7 8 13 9 10
# 3: b 1 9 21 11 13 23 15 17
# 4: c 2 3 9 4 5 10 6 7
# 5: a 1 18 42 22 26 46 30 34
一个base R
选项是
dat[paste0('X', 1:6)] <- Map(add, list(dat$X0), z)
aggregate(.~fact1+fact2, dat, FUN=sum)
# fact1 fact2 X0 X1 X2 X3 X4 X5 X6
#1 a 1 18 42 22 26 46 30 34
#2 b 1 9 21 11 13 23 15 17
#3 a 2 6 12 7 8 13 9 10
#4 b 2 19 31 21 23 33 25 27
#5 c 2 3 9 4 5 10 6 7
或一步到位
aggregate(.~fact1+fact2, cbind(dat, mapply(add, list(dat$X0), z)), FUN=sum)
我正在努力学习 data.table 语法。我掌握了简单摘要的大部分基础知识,但我不知道如何使用 data.table 从现有列生成新列并进行摘要。
这是一个 MWE 示例,我使用 dplyr 和 base 工具从一列创建多列,然后通过分组变量进行汇总:
当前输入
## fact1 fact2 X0
## 1 b 2 9
## 2 a 2 6
## 3 b 1 7
## 4 c 2 3
## 5 a 1 8
## 6 a 1 4
## 7 a 1 5
## 8 a 1 1
## 9 b 1 2
## 10 b 2 10
Base + dlyr 代码
set.seed(10)
dat <- data.frame(
fact1 = factor(sample(c('a', 'b', 'c'), 10, TRUE)),
fact2 = factor(sample(1:2, 10, TRUE)),
X0 = sample(1:10, 10)
)
add <- function(x, y) x + y
z <- sample(1:10, 6, FALSE)
library(dplyr)
z %>%
lapply(., add, dat[, 'X0']) %>%
do.call(cbind, .) %>%
cbind(dat, .) %>%
data.frame() %>%
group_by(fact1, fact2) %>%
summarise_each(funs(sum))
期望输出
## Source: local data frame [5 x 9]
## Groups: fact1
##
## fact1 fact2 X0 X1 X2 X3 X4 X5 X6
## 1 a 1 18 42 22 26 46 30 34
## 2 a 2 6 12 7 8 13 9 10
## 3 b 1 9 21 11 13 23 15 17
## 4 b 2 19 31 21 23 33 25 27
## 5 c 2 3 9 4 5 10 6 7
虽然我要求 data.table 具体解决方案,但我认为看到 base 和 dplyr 等聪明的解决方案可能会使这个问题吸引更广泛的 reader。
可能有更好的方法
library(data.table)
setDT(dat)[, paste0("X", 1:6):= lapply(z, add, X0),
][, lapply(.SD, sum), by = .(fact1, fact2)]
# fact1 fact2 X0 X1 X2 X3 X4 X5 X6
# 1: b 2 19 31 21 23 33 25 27
# 2: a 2 6 12 7 8 13 9 10
# 3: b 1 9 21 11 13 23 15 17
# 4: c 2 3 9 4 5 10 6 7
# 5: a 1 18 42 22 26 46 30 34
一个base R
选项是
dat[paste0('X', 1:6)] <- Map(add, list(dat$X0), z)
aggregate(.~fact1+fact2, dat, FUN=sum)
# fact1 fact2 X0 X1 X2 X3 X4 X5 X6
#1 a 1 18 42 22 26 46 30 34
#2 b 1 9 21 11 13 23 15 17
#3 a 2 6 12 7 8 13 9 10
#4 b 2 19 31 21 23 33 25 27
#5 c 2 3 9 4 5 10 6 7
或一步到位
aggregate(.~fact1+fact2, cbind(dat, mapply(add, list(dat$X0), z)), FUN=sum)