如何在R中的特定条件下对向量的元素进行求和?
How to cumsum the elements of a vector under certain condition in R?
我的objective是对向量的元素进行累加和,并将结果分配给每个元素。但当达到一定条件时,则重置累计和。
例如:
vector_A <- c(1, 1, -1, -1, -1, 1, -1, -1, 1, -1)
现在,假设重置累计和的条件是下一个元素有不同的符号。
那么期望的输出是:
vector_B <- c(1, 2, -1, -2, -3, 1, -1, -2, 1, -1)
我怎样才能做到这一点?
想到的方法是找到由定义的 运行s (rle()
)
数据中的条件 (sign()
),分别对每个 运行 应用 cumsum()
(tapply()
),然后连接回向量 (unlist()
)。某物
像这样:
vector_A <- c(1, 1, -1, -1, -1, 1, -1, -1, 1, -1)
run_length <- rle(sign(vector_A))$lengths
run_id <- rep(seq_along(run_length), run_length)
unlist(tapply(vector_A, run_id, cumsum), use.names = FALSE)
#> [1] 1 2 -1 -2 -3 1 -1 -2 1 -1
稍微总结一下这个过程,我可能会找到分组因子(运行
索引)在函数中?然后分组摘要将需要使用
现有工具,如上面的 tapply()
,或创意 ave()
,或在
数据帧的上下文,group_by()
和 summarise()
with dplyr.
run_index <- function(x) {
with(rle(x), rep(seq_along(lengths), lengths))
}
ave(vector_A, run_index(sign(vector_A)), FUN = cumsum)
#> [1] 1 2 -1 -2 -3 1 -1 -2 1 -1
您可以使用自定义函数代替 cumsum
并使用例如purrr::accumulate
:
library(purrr)
vector_A <- c(1, 1, -1, -1, -1, 1, -1, -1, 1, -1)
purrr::accumulate(vector_A, function(a,b) {
if (sign(a) == sign(b))
a+b
else
b
})
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
或者如果您想避免任何分支:
purrr::accumulate(vector_A, function(a,b) { b + a*(sign(a) == sign(b))})
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
具有 Reduce
的基础 R 选项
> Reduce(function(x, y) ifelse(x * y > 0, x + y, y), vector_A, accumulate = TRUE)
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
或使用 ave
+ cumsum
> ave(vector_A, cumsum(c(1, diff(sign(vector_A)) != 0)), FUN = cumsum)
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
使用ave
:
ave(vector_A, data.table::rleid(sign(A)), FUN = cumsum)
# [1] 1 2 -1 -2 -3 1 -1 -2 1 -1
accumulate
的公式版本:
purrr::accumulate(vector_A, ~ ifelse(sign(.x) == sign(.y), .x + .y, .y))
# [1] 1 2 -1 -2 -3 1 -1 -2 1 -1
我的objective是对向量的元素进行累加和,并将结果分配给每个元素。但当达到一定条件时,则重置累计和。
例如:
vector_A <- c(1, 1, -1, -1, -1, 1, -1, -1, 1, -1)
现在,假设重置累计和的条件是下一个元素有不同的符号。
那么期望的输出是:
vector_B <- c(1, 2, -1, -2, -3, 1, -1, -2, 1, -1)
我怎样才能做到这一点?
想到的方法是找到由定义的 运行s (rle()
)
数据中的条件 (sign()
),分别对每个 运行 应用 cumsum()
(tapply()
),然后连接回向量 (unlist()
)。某物
像这样:
vector_A <- c(1, 1, -1, -1, -1, 1, -1, -1, 1, -1)
run_length <- rle(sign(vector_A))$lengths
run_id <- rep(seq_along(run_length), run_length)
unlist(tapply(vector_A, run_id, cumsum), use.names = FALSE)
#> [1] 1 2 -1 -2 -3 1 -1 -2 1 -1
稍微总结一下这个过程,我可能会找到分组因子(运行
索引)在函数中?然后分组摘要将需要使用
现有工具,如上面的 tapply()
,或创意 ave()
,或在
数据帧的上下文,group_by()
和 summarise()
with dplyr.
run_index <- function(x) {
with(rle(x), rep(seq_along(lengths), lengths))
}
ave(vector_A, run_index(sign(vector_A)), FUN = cumsum)
#> [1] 1 2 -1 -2 -3 1 -1 -2 1 -1
您可以使用自定义函数代替 cumsum
并使用例如purrr::accumulate
:
library(purrr)
vector_A <- c(1, 1, -1, -1, -1, 1, -1, -1, 1, -1)
purrr::accumulate(vector_A, function(a,b) {
if (sign(a) == sign(b))
a+b
else
b
})
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
或者如果您想避免任何分支:
purrr::accumulate(vector_A, function(a,b) { b + a*(sign(a) == sign(b))})
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
具有 Reduce
> Reduce(function(x, y) ifelse(x * y > 0, x + y, y), vector_A, accumulate = TRUE)
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
或使用 ave
+ cumsum
> ave(vector_A, cumsum(c(1, diff(sign(vector_A)) != 0)), FUN = cumsum)
[1] 1 2 -1 -2 -3 1 -1 -2 1 -1
使用ave
:
ave(vector_A, data.table::rleid(sign(A)), FUN = cumsum)
# [1] 1 2 -1 -2 -3 1 -1 -2 1 -1
accumulate
的公式版本:
purrr::accumulate(vector_A, ~ ifelse(sign(.x) == sign(.y), .x + .y, .y))
# [1] 1 2 -1 -2 -3 1 -1 -2 1 -1