【问题标题】:R cumulative sum by condition with resetR按条件累积和复位
【发布时间】:2016-01-04 19:01:54
【问题描述】:

我在 data.frame 中有一个数字向量,如下所示。

df <- data.frame(a = c(1,2,3,4,2,3,4,5,8,9,10,1,2,1))

我需要创建一个新列,该列提供大于其前身的条目的运行计数。结果列向量应该是这样的:

0,1,2,3,0,1,2,3,4,5,6,0,1,0

我的尝试是创建一个“标志”列的差异来标记值何时更大。

df$flag <- c(0,diff(df$a)>0)
> df$flag
 [1] 0 1 1 1 0 1 1 1 1 1 1 0 1 0

然后我可以应用一些 dplyr group/sum 魔法来几乎得到正确的答案,除了当 flag == 0 时总和不会重置:

df %>% group_by(flag) %>% mutate(run=cumsum(flag))

    a flag run
1   1    0   0
2   2    1   1
3   3    1   2
4   4    1   3
5   2    0   0
6   3    1   4
7   4    1   5
8   5    1   6
9   8    1   7
10  9    1   8
11 10    1   9
12  1    0   0
13  2    1  10
14  1    0   0

我不想求助于 for() 循环,因为我有几个这样的运行总和要计算 data.frame 中的数十万行。

【问题讨论】:

    标签: r dplyr cumulative-sum


    【解决方案1】:

    这是ave的一种方式:

    ave(df$a, cumsum(c(F, diff(df$a) < 0)), FUN=seq_along) - 1
     [1] 0 1 2 3 0 1 2 3 4 5 6 0 1 0
    

    我们可以获得按diff(df$a) &lt; 0 分组的运行计数。向量中的哪些位置比它们的前辈少。我们添加c(F, ..) 来说明第一个位置。该向量的累积和创建了一个用于分组的索引。函数ave 可以对该索引执行函数,我们使用seq_along 进行运行计数。但由于它从 1 开始,我们减去一个 ave(...) - 1 以从 0 开始。


    使用dplyr的类似方法:

    library(dplyr)
    df %>% 
      group_by(cumsum(c(FALSE, diff(a) < 0))) %>% 
      mutate(row_number() - 1)
    

    【讨论】:

    • dplyr(根据标签)df %&gt;% group_by(cumsum(c(FALSE, diff(a) &lt; 0))) %&gt;% mutate(row_number() - 1)
    • 哇,谢谢。为我工作。我一直试图用 ave 或 rle 来做这件事,但不能把它们放在一起。
    • 感谢@DavidArenburg。补充 :) 虽然我认为标签是出于暗示目的而不是必需的方法。
    • 是的,我没有嫁给 dplyr,我只是认为这是合乎逻辑的方向。两个答案看起来都很棒。我会做一些时间基准,看看什么在我的情况下最有效。再次感谢;从昨天开始就被困了这么多小时。
    【解决方案2】:

    你不需要 dplyr:

    fun <- function(x) {
      test <- diff(x) > 0
      y <- cumsum(test)
      c(0, y - cummax(y * !test))
    }
    
    fun(df$a)
    [1] 0 1 2 3 0 1 2 3 4 5 6 0 1 0
    

    【讨论】:

    • 我在 SO 上看到过类似的东西,但再也找不到了。我真的很想给予适当的信任。
    【解决方案3】:
    a <- c(1,2,3,4,2,3,4,5,8,9,10,1,2,1)
    f <- c(0, diff(a)>0)
    ifelse(f, cumsum(f), f)
    

    它没有重置。
    重置:

    unlist(tapply(f, cumsum(c(0, diff(a) < 0)), cumsum))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-12
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-05
      • 1970-01-01
      相关资源
      最近更新 更多