具有复位条件的R累积和

nsy*_*mms 4 r cumulative-sum dplyr

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

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

我需要创建一个新列,它提供比其前任更大的条目的运行计数.生成的列向量应为:

0,1,2,3,0,1,2,3,4,5,6,0,1,0
Run Code Online (Sandbox Code Playgroud)

我的尝试是创建一个diffs的"flag"列,以便在值更大时进行标记.

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
Run Code Online (Sandbox Code Playgroud)

然后我可以应用一些dplyr组/ 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
Run Code Online (Sandbox Code Playgroud)

我不想使用for()循环,因为我有几个这样的运行总和来计算data.frame中的几十万行.

Pie*_*une 13

这是一种方式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
Run Code Online (Sandbox Code Playgroud)

我们可以得到一个分组的运行计数diff(df$a) < 0.向量中哪些位置比其前辈少.我们添加c(F, ..)到第一个位置的帐户.该向量的累积总和创建分组索引.该函数ave可以对该索引执行一个函数,我们seq_along用于运行计数.但是从1开始,我们减去1 ave(...) - 1从零开始.


类似的方法使用dplyr:

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

  • 哇谢谢.适合我.我一直试图用ave或rle做这个,但不能把它放在一起. (2认同)

Rol*_*and 10

你不需要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
Run Code Online (Sandbox Code Playgroud)

  • 我已经在SO上看过这样的东西了,但是再也找不到了.我真的想给予适当的信任. (2认同)