两列的条件累计和
Conditional cumulative sum from two columns
我无法解决以下问题。
假设数据如下:
library(tidyverse)
df <- tibble(source = c("A", "A", "B", "B", "B", "C"),
value = c(5, 10, NA, NA, NA, 20),
add = c(1, 1, 1, 2, 3, 4))
我想做的是:对于所有source == "B"
的情况,我想计算前一行的value
和当前行的add
的累加和。当然,对于第一个“B”行,我需要提供 value
的起始值。注意:在这种情况下,如果我们只取最后一个“A”行的值就可以了。
因此对于第 3 行,结果为 10 + 1 = 11。
对于第 4 行,结果为 11 + 2 = 13。
对于第 5 行,结果为 13 + 3 = 16。
我尝试使用 purrr::accumulate
,但我在很多方面都失败了,例如我以为我可以做到:
df %>%
mutate(test = accumulate(add, .init = 10, ~.x + .y))
但这会导致错误:
Error: Problem with `mutate()` column `test`.
i `test = accumulate(add, .init = 10, ~.x + .y)`.
i `test` must be size 6 or 1, not 7.
如果我使用 .init = value
也一样
而且我也没有设法只在 B 组上完成这项工作(虽然这可能不是问题,但我想我可以在完整的数据帧上执行,然后只替换所有非 B 行的值).
预期输出:
# A tibble: 6 x 4
source value add test
<chr> <dbl> <dbl> <dbl>
1 A 5 1 NA
2 A 10 1 NA
3 B NA 1 11
4 B NA 2 13
5 B NA 3 16
6 C 20 4 NA
@tmfmnk 提供了一个很棒的答案,他们值得完全信任(不是我)
下面是他们评论中的相同代码(为了提高可见性,同时还设置了初始值)
init_value = 10
df = df %>%
mutate(test = lag(value)) %>%
group_by(source) %>%
mutate(test = init_value + cumsum(add))
你基本上是在正确的方向。由于您向 accumulate
提供了一个 .init
值,因此生成的向量大小为 n+1
,第一个值为 .init
。您必须删除第一个值才能获得适合列大小的向量。
然后,如果您希望对剩余值使用 NA,可以使用以下方法。此外,由于“起始行”是第三行,因此 .init
必须设置为 8。
df %>%
mutate(test =
ifelse(source == "B", accumulate(add, .init = 8, ~.x + .y)[-1], NA))
# A tibble: 6 x 4
source value add test
<chr> <dbl> <dbl> <dbl>
1 A 5 1 NA
2 A 10 1 NA
3 B NA 1 11
4 B NA 2 13
5 B NA 3 16
6 C 20 4 NA
我无法解决以下问题。
假设数据如下:
library(tidyverse)
df <- tibble(source = c("A", "A", "B", "B", "B", "C"),
value = c(5, 10, NA, NA, NA, 20),
add = c(1, 1, 1, 2, 3, 4))
我想做的是:对于所有source == "B"
的情况,我想计算前一行的value
和当前行的add
的累加和。当然,对于第一个“B”行,我需要提供 value
的起始值。注意:在这种情况下,如果我们只取最后一个“A”行的值就可以了。
因此对于第 3 行,结果为 10 + 1 = 11。
对于第 4 行,结果为 11 + 2 = 13。
对于第 5 行,结果为 13 + 3 = 16。
我尝试使用 purrr::accumulate
,但我在很多方面都失败了,例如我以为我可以做到:
df %>%
mutate(test = accumulate(add, .init = 10, ~.x + .y))
但这会导致错误:
Error: Problem with `mutate()` column `test`.
i `test = accumulate(add, .init = 10, ~.x + .y)`.
i `test` must be size 6 or 1, not 7.
如果我使用 .init = value
而且我也没有设法只在 B 组上完成这项工作(虽然这可能不是问题,但我想我可以在完整的数据帧上执行,然后只替换所有非 B 行的值).
预期输出:
# A tibble: 6 x 4
source value add test
<chr> <dbl> <dbl> <dbl>
1 A 5 1 NA
2 A 10 1 NA
3 B NA 1 11
4 B NA 2 13
5 B NA 3 16
6 C 20 4 NA
@tmfmnk 提供了一个很棒的答案,他们值得完全信任(不是我)
下面是他们评论中的相同代码(为了提高可见性,同时还设置了初始值)
init_value = 10 df = df %>% mutate(test = lag(value)) %>% group_by(source) %>% mutate(test = init_value + cumsum(add))
你基本上是在正确的方向。由于您向 accumulate
提供了一个 .init
值,因此生成的向量大小为 n+1
,第一个值为 .init
。您必须删除第一个值才能获得适合列大小的向量。
然后,如果您希望对剩余值使用 NA,可以使用以下方法。此外,由于“起始行”是第三行,因此 .init
必须设置为 8。
df %>%
mutate(test =
ifelse(source == "B", accumulate(add, .init = 8, ~.x + .y)[-1], NA))
# A tibble: 6 x 4
source value add test
<chr> <dbl> <dbl> <dbl>
1 A 5 1 NA
2 A 10 1 NA
3 B NA 1 11
4 B NA 2 13
5 B NA 3 16
6 C 20 4 NA