我已经用我脑子里的许多方式搜索了这个问题,我仍然找不到答案.我是R的新手,所以有些事情让我感到困惑.
假设我有一个这样的数据表:
x y z 100 200 300
1: 1 1 a 1 1 1
2: 1 1 b 2 3 4
3: 1 2 c 3 5 7
4: 1 2 d 4 7 0
5: 2 1 e 5 9 3
6: 2 1 f 6 1 6
7: 2 2 g 7 3 9
8: 2 2 h 8 5 2
Run Code Online (Sandbox Code Playgroud)
这可以用这段代码创建:
DT = setDT(structure(list(c(1, 1, 1, 1, 2, 2, 2, 2),
c(1, 1, 2, 2, 1, 1, 2, 2),
c("a","b","c","d","e","f","g","h"),
c(1,2,3,4,5,6,7,8),
c(1,3,5,7,9,1,3,5),
c(1,4,7,0,3,6,9,2)),
.Names = c("x", "y", "z", 100, 200, 300), row.names = c(NA, -8L), class = "data.frame"))
Run Code Online (Sandbox Code Playgroud)
但是,在我的实际代码中,最后三列是使用另一个函数(dcast)自动生成的,因此它的总列数data.table不是静态的.此外,您可能会注意到这三个最后一列的名称是数字,这在某些时候可能是个问题.
我需要的是为每个"额外"列创建一个aditional列(在"z"列之后的列).我需要代码才能工作,比如这个例子:首先,它创建列"100s",然后对于每一行,它计算列"100"的总和,只考虑具有相同组合的行x,y即所讨论的行.等等"200s"和"300s".像这样:
x y z 100 200 300 100s 200s 300s
1: 1 1 a 1 1 1 3 4 5
2: 1 1 b 2 3 4 3 4 5
3: 1 2 c 3 5 7 7 12 7
4: 1 2 d 4 7 0 7 12 7
5: 2 1 e 5 9 3 11 10 9
6: 2 1 f 6 1 6 11 10 9
7: 2 2 g 7 3 9 15 8 11
8: 2 2 h 8 5 2 15 8 11
Run Code Online (Sandbox Code Playgroud)
我试过对这个代码的想法进行了几处修改:
for (i in 3:(dim(DT)[2])) {
DT <- DT[,paste(colnames(DT)[i], "s", sep=""):=sum(i),
by=c("x","y")]
}
Run Code Online (Sandbox Code Playgroud)
这给了我以下结果:
x y z 100 200 300 100s 200s 300s
1: 1 1 a 1 1 1 4 5 6
2: 1 1 b 2 3 4 4 5 6
3: 1 2 c 3 5 7 4 5 6
4: 1 2 d 4 7 0 4 5 6
5: 2 1 e 5 9 3 4 5 6
6: 2 1 f 6 1 6 4 5 6
7: 2 2 g 7 3 9 4 5 6
8: 2 2 h 8 5 2 4 5 6
Run Code Online (Sandbox Code Playgroud)
当然,R没有将i的数值识别为它应该考虑的总和列数,而是将其作为原始数字.我无法弄清楚如何通过其位置来处理特定列,因为当涉及到sum()时,"with = FALSE"事件无法保存当天.
任何帮助将不胜感激.
for在这种情况下,不需要使用循环来获得所需的结果.您可以DT通过参考更新:
DT[, paste0(colnames(DT)[3:5],'s') := lapply(.SD, sum), by = .(x,y)]
Run Code Online (Sandbox Code Playgroud)
这将给你想要的结果:
> DT
x y 100 200 300 100s 200s 300s
1: 1 1 1 1 1 3 4 5
2: 1 1 2 3 4 3 4 5
3: 1 2 3 5 7 7 12 7
4: 1 2 4 7 0 7 12 7
5: 2 1 5 9 3 11 10 9
6: 2 1 6 1 6 11 10 9
7: 2 2 7 3 9 15 8 11
8: 2 2 8 5 2 15 8 11
Run Code Online (Sandbox Code Playgroud)
如果您不知道要汇总哪些列,可以使用以下方法之一:
# method 1:
DT[, paste0(colnames(DT)[3:ncol(DT)],'s') := lapply(.SD, sum), by = .(x,y)]
# method 2:
DT[, paste0(setdiff(colnames(DT), c('x','y')),'s') := lapply(.SD, sum), by = .(x,y)]
Run Code Online (Sandbox Code Playgroud)
通过更新的示例,可能最好的方法是:
cols <- setdiff(colnames(DT), c('x','y','z'))
DT[, paste0(cols,'s') := lapply(.SD, sum), by = .(x,y), .SDcols = cols]
Run Code Online (Sandbox Code Playgroud)
这使:
> DT
x y z 100 200 300 100s 200s 300s
1: 1 1 a 1 1 1 3 4 5
2: 1 1 b 2 3 4 3 4 5
3: 1 2 c 3 5 7 7 12 7
4: 1 2 d 4 7 0 7 12 7
5: 2 1 e 5 9 3 11 10 9
6: 2 1 f 6 1 6 11 10 9
7: 2 2 g 7 3 9 15 8 11
8: 2 2 h 8 5 2 15 8 11
Run Code Online (Sandbox Code Playgroud)