You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Tidyverse中如何递归应用函数填充数据列缺失值?

递归填充分组数据中的缺失值(自定义规则)

原始数据

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

数据结构如下:

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

需求

对每个分组,保留非NA的value值,从第一个NA值开始,递归应用自定义函数(示例为每年增加10,即valueₜ = valueₜ₋₁ + 10)填充后续缺失值。

尝试过的方法及局限性

  • dplyr::lag方法:仅能填充第一个NA,无法实现递归填充,因为它是向量化操作,不依赖前一次计算的结果:
library(dplyr)
data %>% 
  group_by(group) %>% 
  mutate(value_fix = dplyr::lag(value) + 10)

输出仅能填充第一个NA,后续NA仍为空。

  • tidyr::fill方法:只能用前一个非NA值填充,不支持自定义递归计算逻辑:
data %>% 
  group_by(group) %>% 
  tidyr::fill(value)
  • 已有的繁琐解决方案:通过额外生成last_value列再结合purrr::accumulate实现,但代码冗余可读性差:
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)
  ))

更简洁的Tidyverse解决方案

可以直接用purrr::accumulate结合coalesce实现,代码简洁且逻辑清晰:

library(tidyverse)

data %>%
  group_by(group) %>%
  mutate(value_fix = accumulate(value, ~ coalesce(.y, .x + 10))) %>%
  ungroup()

输出结果

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

逻辑说明

accumulate是递归迭代函数,每次处理一个元素时:

  • 如果当前value(.y)非NA,直接保留该值;
  • 如果当前value是NA,就用上一次迭代的结果(.x)加上10作为填充值。
    整个过程完全符合需求,且无需额外中间列,代码简洁易读。

内容的提问来源于stack exchange,提问作者elikesprogramming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 14:09:26