基于不同表的行值对表中的列值求和

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于不同表的行值对表中的列值求和相关的知识,希望对你有一定的参考价值。

我想基于不同表DT1的行值对表DT2中的列值求和,并将其存储在DT3中

library(data.table)
DT1 <- data.table(x = seq(1,100, by = 1), 
                 y = round(runif(100,50, 60)),
                 z = round(runif(100, 61, 70)))

DT2 <- data.table(a = seq(1, 1000, by = 1),
                 b = round(rnorm(1000, 10,1)),
                 c = round(rnorm(1000, 20,1)),
                 d = round(rnorm(1000, 30,1)))

初始化DT3

DT3 <- DT1[,.(x)]
DT3[,':='(e = 0,
          f = 0,
          g = 0)]

使用for循环来求和值

for(i in 1:nrow(DT1)){
  DT3[i, 2:4] <- DT2[DT1[i,y]:DT1[i,z], 
                     lapply(.SD, sum),
                     .SDcols = c("b", "c", "d")]
}

这很好用。唯一的问题是DT1和DT2中的行数和列数增加需要很多时间。我有超过100000行的DT1。这需要我大约30分钟。有没有更快的方法来执行此操作?

答案

你可以试试这个:

library(data.table)
DT1 <- data.table(x = seq(1,100, by = 1), 
                 y = round(runif(100,50, 60)),
                 z = round(runif(100, 61, 70)))

DT2 <- data.table(a = seq(1, 1000, by = 1),
                 b = round(rnorm(1000, 10,1)),
                 c = round(rnorm(1000, 20,1)),
                 d = round(rnorm(1000, 30,1)))

matrix(DT1[, colSums(DT2[, -"a"][as.numeric(y:z)]), 1:nrow(DT1)]$V1,
       ncol = 3, byrow = TRUE)

  #      [,1] [,2] [,3]
  # [1,]  114  223  324
  # [2,]   73  141  208
  # [3,]  112  222  323
  # [4,]  151  301  443
  # [5,]  133  263  382
  # ...

迭代DT1行并提取矢量y:zas.numeric(y:z))。将此向量传递给DT2并获取colSums

另一答案

就单次迭代而言,您的代码已经很有效。您正在使用data.table而不是dataframe,而lapply语句也是有效的。

因此,我认为主要的优化应该集中在你如何应用sum语句。

1.避免重复计算:

在您的数据上检查table(duplicated(DT1[,c("y", "z")]))的结果。对于伪数据情况,重复30%的求和操作。如果您的数据具有如此高的重复率,我建议先计算唯一的y & z的结果,然后将结果分配给主数据表。 。

2.并行化循环:您的迭代是独立的,这使得循环可以并行化。检查foreach包。但请注意.combine参数/函数,因为这可能会极大地减少结果组合开销。

以上是关于基于不同表的行值对表中的列值求和的主要内容,如果未能解决你的问题,请参考以下文章

使用 ASP.Net 在 SQL 中对表的列值求和时出现异常

MySQL - 基于同一表中的行求和列值

如何在sqlite中对表中的行进行排名?

基于列值向sql中的列添加行值

根据另一个表中的列值选择一个表中的行?

根据第三个表中的列值删除表中的行