gpt4 book ai didi

r - 向下填充一列,递归地将函数应用于前一个值

转载 作者:行者123 更新时间:2023-12-02 01:30:05 25 4
gpt4 key购买 nike

考虑这个数据

data <- data.frame(
group = c(rep("A", 10), rep("B", 10)),
year = rep(2016:2025, 2),
value = c(10, 20, 30, 40, NA, NA, NA, NA, NA, NA,
70, 80, NA, NA, NA, NA, NA, NA, NA, NA)
)
data
#> group year value
#> 1 A 2016 10
#> 2 A 2017 20
#> 3 A 2018 30
#> 4 A 2019 40
#> 5 A 2020 NA
#> 6 A 2021 NA
#> 7 A 2022 NA
#> 8 A 2023 NA
#> 9 A 2024 NA
#> 10 A 2025 NA
#> 11 B 2016 70
#> 12 B 2017 80
#> 13 B 2018 NA
#> 14 B 2019 NA
#> 15 B 2020 NA
#> 16 B 2021 NA
#> 17 B 2022 NA
#> 18 B 2023 NA
#> 19 B 2024 NA
#> 20 B 2025 NA

现在我想应用任意函数来填充缺失值递归到最后一个非缺失值。

例如,假设我想要让这些值每年增加 10 个点。

因此,对于 value 不为 NA 的行,它应该保持不变。从 value 为 NA 的行开始,它应用该 valuet = valuet − 1 + 10

一个天真的尝试是使用dplyr::lag,但这仅适用于第一个缺失值,因为 lag 是矢量化的并且对 value 向量进行操作,并且不会递归之前的 value

library(dplyr)
data |>
group_by(group) |>
mutate(value_fix = dplyr::lag(value) + 10)
#> # A tibble: 20 × 4
#> # Groups: group [2]
#> group year value value_fix
#> <chr> <int> <dbl> <dbl>
#> 1 A 2016 10 NA
#> 2 A 2017 20 20
#> 3 A 2018 30 30
#> 4 A 2019 40 40
#> 5 A 2020 NA 50
#> 6 A 2021 NA NA
#> 7 A 2022 NA NA
#> 8 A 2023 NA NA
#> 9 A 2024 NA NA
#> 10 A 2025 NA NA
#> 11 B 2016 70 NA
#> 12 B 2017 80 80
#> 13 B 2018 NA 90
#> 14 B 2019 NA NA
#> 15 B 2020 NA NA
#> 16 B 2021 NA NA
#> 17 B 2022 NA NA
#> 18 B 2023 NA NA
#> 19 B 2024 NA NA
#> 20 B 2025 NA NA

这是我认为 tidyr 可以提供帮助的地方,因为它有点相似tidyr::fill

data |> 
group_by(group) |>
tidyr::fill(value)

但理想情况下,使用 .f 参数递归地应用于最后一个值。好像没有这样的事情。

谷歌搜索我想出了这个解决方案

data |> 
group_by(group) |>
mutate(last_value = case_when(
value == dplyr::last(na.omit(value)) ~ value,
TRUE ~ NA_real_
)) |>
mutate(value_fix = purrr::accumulate(
.x = last_value,
.f = ~ coalesce(.x + 10, .y)
))
#> # A tibble: 20 × 5
#> # Groups: group [2]
#> group year value last_value value_fix
#> <chr> <int> <dbl> <dbl> <dbl>
#> 1 A 2016 10 NA NA
#> 2 A 2017 20 NA NA
#> 3 A 2018 30 NA NA
#> 4 A 2019 40 40 40
#> 5 A 2020 NA NA 50
#> 6 A 2021 NA NA 60
#> 7 A 2022 NA NA 70
#> 8 A 2023 NA NA 80
#> 9 A 2024 NA NA 90
#> 10 A 2025 NA NA 100
#> 11 B 2016 70 NA NA
#> 12 B 2017 80 80 80
#> 13 B 2018 NA NA 90
#> 14 B 2019 NA NA 100
#> 15 B 2020 NA NA 110
#> 16 B 2021 NA NA 120
#> 17 B 2022 NA NA 130
#> 18 B 2023 NA NA 140
#> 19 B 2024 NA NA 150
#> 20 B 2025 NA NA 160

这可行,但似乎有点老套且不易阅读。只编写循环并感到高兴会更干净。

我真的认为对于这样一个简单的情况,在 tidyverse 中会有一种内置的方式(矢量化、可读代码)来完成它。但我找不到任何东西。我错过了什么吗?有什么想法可以更好地做到这一点吗?

创建于 2022-08-30 reprex v2.0.2

最佳答案

custom_fun <- function(x, y) {
if(is.na(y)) x + 10 else y
}


data %>%
group_by(group)%>%
mutate(value = accumulate(value, custom_fun))

# Groups: group [2]
group year value
<chr> <int> <dbl>
1 A 2016 10
2 A 2017 20
3 A 2018 30
4 A 2019 40
5 A 2020 50
6 A 2021 60
7 A 2022 70
8 A 2023 80
9 A 2024 90
10 A 2025 100
11 B 2016 70
12 B 2017 80
13 B 2018 90
14 B 2019 100
15 B 2020 110
16 B 2021 120
17 B 2022 130
18 B 2023 140
19 B 2024 150
20 B 2025 160

关于r - 向下填充一列,递归地将函数应用于前一个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73535779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com