具有复位条件的R累积和

时间:2015-10-07 13:51:30

标签: r dplyr cumulative-sum

我在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

我的尝试是创建一个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

然后我可以应用一些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

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

3 个答案:

答案 0 :(得分: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

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

使用dplyr的类似方法:

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

答案 1 :(得分:8)

你不需要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

答案 2 :(得分:2)

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))