如何在sum()语句中通过其位置引用data.table的列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在sum()语句中通过其位置引用data.table的列相关的知识,希望对你有一定的参考价值。

我已经用我脑子里的许多方式搜索了这个问题,我仍然找不到答案。我是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

这可以用这段代码创建:

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"))

但是,在我的实际代码中,最后三列是使用另一个函数(dcast)自动生成的,因此data.table的列总数不是静态的。此外,您可能会注意到这三个最后一列的名称是数字,这在某些时候可能是个问题。

我需要的是为每个“额外”列创建一个aditional列(在“z”列之后的列)。我需要代码才能工作,比如这个例子:首先,它创建列“100s”,然后对于每一行,它计算列“100”的总和,只考虑具有相同组合的xy行的行有问题。等等“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

我试过对这个代码的想法进行了几处修改:

for (i in 3:(dim(DT)[2])) {
  DT <- DT[,paste(colnames(DT)[i], "s", sep=""):=sum(i),
                   by=c("x","y")]
}

这给了我以下结果:

   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

当然,R不会将i的数值识别为它应该考虑的总和列数,而是将其作为原始数字。我无法弄清楚如何通过其位置来处理特定列,因为当涉及到sum()时,“with = FALSE”事情无法保存当天。

任何帮助将不胜感激。

答案

在这种情况下,不需要使用for循环来获得所需的结果。您可以通过以下方式更新DT

DT[, paste0(colnames(DT)[3:5],'s') := lapply(.SD, sum), by = .(x,y)]

这将给你想要的结果:

> 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

如果您不确切地知道要汇总的列,可以使用以下方法之一:

# 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)]

通过更新的示例,可能最好的方法是:

cols <- setdiff(colnames(DT), c('x','y','z'))
DT[, paste0(cols,'s') := lapply(.SD, sum), by = .(x,y), .SDcols = cols]

这使:

> 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

以上是关于如何在sum()语句中通过其位置引用data.table的列的主要内容,如果未能解决你的问题,请参考以下文章

如何在C ++中通过其名称获取进程句柄?

如何使用python在selenium中通过其id名称的一部分查找元素

如何使用存储库接口在 Spring Data 中通过其嵌套对象的 objectId 查找集合?

使用AngularJS方式在对象数组中通过其属性查找对象

在python的List中通过其成员查找对象

在python中通过其相似性进行图像聚类