【问题标题】:Cumulative sum in data table, but using a group-by for each row数据表中的累积和,但对每一行使用分组
【发布时间】:2019-06-04 19:14:13
【问题描述】:

假设我有一个如下的 data.table(您可以将 w 视为一个分组变量):

set.seed(1)
prQ = CJ(Q1 = 1:10, Q2=1:10,w=1:2)
prQ[,pQ:=runif(100,0,1)]
prQ[,pQ:=pQ/sum(pQ),by=w]

  > prQ
     Q1 Q2 w          pQ
  1:  1  1 1 0.004889560
  2:  1  1 2 0.007553012
  3:  1  2 1 0.010549565
  4:  1  2 2 0.018433927
  5:  1  3 1 0.003714138
 ---                    
196: 10  8 2 0.016183006
197: 10  9 1 0.008384253
198: 10  9 2 0.008323492
199: 10 10 1 0.014932841
200: 10 10 2 0.012278353

对于给定的 w,我如何计算一个名为 CDF 的新列,该列执行以下操作:

例如假设Q1 = 4 和Q2 = 6。定义一个新列,

CDF = sum(pQ) 对于所有 Q1Q2

例如单行:

CDF0 = sum(prQ[Q1<=4 & Q2<=6 & w==1,pQ])
prQ[Q1==4 & Q2==6,CDF:=CDF0]

我想对给定 w 的所有行执行此操作。

使用蛮力完成所需的输出:

for(w0 in 1:2){
  for(j in 1:10){
    for(p in 1:10){
          CDF0 = sum(prQ[Q1<=j & Q2<=p & w==w0,pQ])
          prQ[Q1==j & Q2==p & w==w0,CDF:=CDF0]

    }
  }
}



  > head(prQ)
   Q1 Q2 w          pQ         CDF
1:  1  1 1 0.004889560 0.004889560
2:  1  1 2 0.007553012 0.007553012
3:  1  2 1 0.010549565 0.015439125
4:  1  2 2 0.018433927 0.025986939
5:  1  3 1 0.003714138 0.019153263
6:  1  3 2 0.018234648 0.044221587

【问题讨论】:

  • @PoGibas - 我认为它比这更复杂 - 我认为它需要是一个自连接,因此所有值小于当前行的行都被求和。跨度>
  • @thelatemail 正确,PoGibas 解决方案不起作用
  • @PoGibas 好的,我现在已经添加了。我使用蛮力方法计算了它。我显然需要比这更有效的东西。 :)
  • 保存到新变量时,我无法让它吐出正确的结果,但prQ[ prQ, on=c("w==w","Q1&lt;=Q1","Q2&lt;=Q2"), sum(pQ), by=.EACHI, allow.cartesian=TRUE ] 似乎很接近。
  • @PoGibas 。它现在不适用于后面的行。如果您尝试使用identical(prQ1, prQ2) 比较答案,其中prQ1 是用蛮力创建的,prQ2 是使用您的代码的答案,它会显示FALSE

标签: r group-by data.table aggregate cumsum


【解决方案1】:

根据pQ 值构造的矩阵中每个可能的子矩阵求和的可能方法(行数 = 唯一 Q2 的数量,列数 = 唯一 Q1 的数量):

#ensure that order is correct as values will be used to generate the matrix 
#so that all elements in the top left sub-matrix will always be 
#smaller than or equal to the bottom right element of this sub-matrix
setorder(prQ, w, Q1, Q2)

#create all possible permutations of row and column indices
subMatIdx <- prQ[, CJ(as.integer(as.factor(Q1)), as.integer(as.factor(Q2)), unique=TRUE)]

#sum every sub matrix
prQ[, CDF :=
    {
        nr <- uniqueN(Q2)

        .(Map(function(i, j) sum(matrix(pQ, nrow=nr)[1L:j, 1L:i]), 
            subMatIdx[["V1"]], subMatIdx[["V2"]]))
    },
    by=.(w)]

输出:

     Q1 Q2 w          pQ        CDF
  1:  1  1 1 0.004889560 0.00488956
  2:  1  2 1 0.010549565 0.01543912
  3:  1  3 1 0.003714138 0.01915326
  4:  1  4 1 0.017396970 0.03655023
  5:  1  5 1 0.011585652 0.04813589
 ---                               
196: 10  6 2 0.001196193  0.5713282
197: 10  7 2 0.017785668  0.6535378
198: 10  8 2 0.016183006  0.7734989
199: 10  9 2 0.008323492   0.871678
200: 10 10 2 0.012278353          1

编辑: 如果 Q1 和 Q2 为负数或任何实数怎么办? subMatIdx 上的线路应该已经处理好了。

例如:

set.seed(1)
prQ = CJ(Q1 = -1:10, Q2=-1:10,w=1:2)
prQ[,pQ:=runif(nrow(prQ),0,1)]
prQ[,pQ:=pQ/sum(pQ),by=w]

setorder(prQ, w, Q1, Q2)

#create all possible permutations of row and column indices
subMatIdx <- prQ[, CJ(as.integer(as.factor(Q1)), 
    as.integer(as.factor(Q2)), unique=TRUE)]

prQ[, CDF := {
        nr <- uniqueN(Q2)

        .(Map(function(i, j) sum(matrix(pQ, nrow=nr)[1L:j, 1L:i]), 
            subMatIdx[["V1"]], subMatIdx[["V2"]]))
    },
    by=.(w)]

输出:

     Q1 Q2 w          pQ         CDF
  1: -1 -1 1 0.003607862 0.003607862
  2: -1  0 1 0.007784212  0.01139207
  3: -1  1 1 0.002740553  0.01413263
  4: -1  2 1 0.012836710  0.02696934
  5: -1  3 1 0.008548709  0.03551805
 ---                                
284: 10  6 2 0.011164332   0.6425251
285: 10  7 2 0.007638237   0.7360602
286: 10  8 2 0.005403923   0.8270053
287: 10  9 2 0.002008067   0.9193811
288: 10 10 2 0.002242777           1

【讨论】:

  • 如果你想使用比 w 更通用的变量集,你如何在“setorder”函数中处理这个?
  • 您的意思是按多个变量分组?如果是,您可以将它们添加到by=.(w,x,y,z,...)setorder 中的 w 旨在查看原始数据集,以便为我的下一步编码
  • 喜欢setorder(prQ, .(w,x,y,z), Q1, Q2)?
  • setorder(prQ, Q1, Q2) 可以。这样左上子矩阵中的所有元素都将始终小于或等于该子矩阵右下角的元素
  • subMatIdx 上的行应该已经处理好了。当我将值转换为整数索引时。
猜你喜欢
  • 2022-11-28
  • 1970-01-01
  • 2013-07-13
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2014-01-03
  • 2020-03-10
  • 1970-01-01
相关资源
最近更新 更多