【问题标题】:Cumulative sum conditional to interval以区间为条件的累积和
【发布时间】:2016-01-08 02:37:48
【问题描述】:

我想计算应用于另一列的一组间隔[n, +∞)(即≥ n)的数据框列的条件总和。在下面的示例数据中,间隔应用于列a,列b 中的值有条件地求和。对于[0, +∞),所有a 列的值都是≥ 0,所以b_sum 是所有值的总和。对于[3, +∞),只有一条记录是≥ 3,所以b_sum 是500。

输入数据

  a    b          
1.1  100          
2.3  150          
0.1   20          
0.5   80          
3.3  500          
1.6  200
1.1  180

期望的结果

n  b_sum
0   1230
1   1130
2    650
3    500
4      0

我确信使用for 循环会很简单;然而;我想避免这种方法并使用矢量化基 Rdplyr 方法。

【问题讨论】:

  • 到目前为止你尝试了什么?
  • @Pascal。我会尝试for 循环,但我知道这不是R 中最有效的方法。我举的例子是微不足道的。实际输入数据可能有超过一百万条记录。我可以在dplyr 中按间隔进行求和,但仅限于每条记录唯一的间隔。我的示例有重叠的间隔。

标签: r dplyr


【解决方案1】:

矢量化解

df <- df[order(df$a), ] # sort by "a" column
ind <- findInterval(0:4, df$a) + 1 
sum(df$b) - cumsum(c(0,  df$b))[ind]
#[1] 1230 1130  650  500    0

【讨论】:

    【解决方案2】:

    我们可以使用vapply

     n <- trunc(min(df1$a)) : ceiling(max(df1$a))
    
    
     b_sum <- vapply(n, function(i) sum(df1$b[!is.na(cut(df1$a,
                         breaks=c(i, Inf)))]), 0)
     b_sum
    #[1] 1230 1130  650  500    0
    data.frame(n, b_sum)
    

    我们也不需要cut

    vapply(n, function(i) sum(df1$b[df1$a>i]), 0)
    #[1] 1230 1130  650  500    0
    

    【讨论】:

    • 感谢@akrun 有效。我尝试了我的 200k 记录数据,它也很快。
    【解决方案3】:

    布尔数学。将向量乘以逻辑条件,得到 0/1

     sapply(0:4, function(n) { sum( (sub("\\..+$", "", inp$a) >= n )*inp$b ) } )
    #[1] 1230 1130  650  500    0
    
    data.frame( n=0:4, 
                b_sum= sapply(0:4, function(n) sum( sub("\\..+$", "", inp$a) >= n)*inp$b) )
    

    【讨论】:

      【解决方案4】:

      另一种可能性:

      data.frame(n = 0:4, b_sum = with(df, sum(b) - c(0, cumsum(tapply(b, floor(a), sum)))))
      

      【讨论】:

        猜你喜欢
        • 2015-07-20
        • 2019-09-04
        • 1970-01-01
        • 1970-01-01
        • 2013-05-20
        • 2019-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多