簡體   English   中英

R按條件累計總和並重置

[英]R cumulative sum by condition with reset

我在 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 中的幾十萬行。

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM