带复位条件的 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
我的尝试是创建一个 "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 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.[=14 中计算数十万行=]
这是 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))
我在 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
我的尝试是创建一个 "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 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.[=14 中计算数十万行=]
这是 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))