我正在使用data.table包尝试一般的聚合数据。我有多个要汇总的列。我使用以下脚本创建初始数据表:
library(data.table)
dt <- data.table(x.1 = rnorm(10, 20, 3), x.2 = rnorm(10, 20, 3), x.3 = rnorm(10, 20, 3),
y.1 = rnorm(10, 20, 3), y.2 = rnorm(10, 20, 3), y.3 = rnorm(10, 20, 3),
z.1 = rnorm(10, 20, 3), z.2 = rnorm(10, 20, 3), z.3 = rnorm(10, 20, 3))
我想要实现的是聚合列{x1,x2,x3,y1,y2,y3,z1,z2,z3} =&gt; {x.total,y.total,z.total}通过对每组列应用和。
我可以使用for循环这样做:
prefixes <- c('x', 'y', 'z')
initial.colnames <- c(names(dt))
for (i in 1:nrow(dt)){
for (pref in prefixes){
dt[,eval(paste0(pref, '.total')) := sum(dt[i, eval(grep(pref, initial.colnames))]), with = TRUE]
}
}
但是,我想使用内联数据表构造来应用,如下所示:
dt[, eval(paste0(prefixes, '.total')) := sum(dt[,eval(grep(prefixes, initial.colnames))]), with = F]
但这并没有给我所需的结果。
也许有一些想法如何以正确的方式做到这一点?
答案 0 :(得分:6)
这是一种与melt
聚合的方式:
mDT = melt(dt[, r := .I], measure.vars = patterns(prefixes), value.name=prefixes)
mDT[, lapply(.SD, sum), by=r, .SDcols=prefixes]
r x y z
1: 1 63.65898 65.41892 56.40470
2: 2 60.58634 62.71055 48.69771
3: 3 50.12036 60.06289 66.38637
4: 4 55.42629 63.38670 56.98914
5: 5 59.94042 54.28727 49.20218
6: 6 59.51313 67.53499 59.24097
7: 7 63.26874 62.23262 60.70875
8: 8 54.90082 76.09135 58.79787
9: 9 56.35402 52.11372 60.37903
10: 10 52.77926 55.06044 53.75093
答案 1 :(得分:5)
我们可以将Map
与Reduce
dt[,paste0(prefixes, '.total'):= Map(function(i) Reduce('+',as.list(.SD[,i, with=FALSE])),
split(names(dt), sub('\\..*', '', names(dt))))]