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

R中高效填充缺失值:基于前序年份线性组合替代循环方案

需求说明

需要在R中按以下规则填充缺失值:

  • 2020年值由2019、2018、2017年值按0.65、0.25、0.10的权重线性组合生成
  • 2021年值由2020、2019、2018年值按相同权重组合生成,后续年份以此类推

数据构造代码

library(data.table) # CJ函数依赖data.table包
comb1 <- cbind(CJ(letters[1:4], 2000:2019), rnorm(80,2,1)) 
comb2 <-  cbind(CJ(letters[1:4], 2020:2024), data.frame(rep(NA, 20)))
colnames(comb1) <- c("state","year","v")
colnames(comb2) <- c("state","year","v")

comb <- rbind(comb1, comb2)
comb <- comb[order(comb$state, comb$year),]

现有实现的性能问题

目前已实现嵌套循环方案,但因数据包含大量state分组,运行速度极慢;后续用向量方式做了部分优化,但仍需更优雅的高效实现方案。

嵌套循环代码

library(dplyr)
vlist <- unique(comb$state)
for (i in vlist) {
  for (j in (2002:2024)) {
    value <- 0.65*comb$v[comb$year==j-1 & comb$state==i] + 0.25*comb$v[comb$year==j-2 & comb$state==i] + 0.10*comb$v[comb$year==j-3 & comb$state==i]
    if (is.na(comb$v[comb$year==j & comb$state==i])) {
      comb$v[comb$year==j & comb$state==i] <- value
    }
  }
}

部分优化的向量代码

for (j in (2002:2024)) {
  
  comb$v_1 <- ave(comb$v, comb$state, FUN = dplyr::lag)
  comb$v_2 <- ave(comb$v_1, comb$state, FUN = dplyr::lag) 
  comb$v_3 <- ave(comb$v_2, comb$state, FUN = dplyr::lag) 
  
  comb$imp <- 0.65*comb$v_1 + 0.25*comb$v_2 + 0.10*comb$v_3
  comb$v <- ifelse(is.na(comb$v)&comb$year==j, comb$imp, comb$v)
  
  comb$v_1 <- NULL
  comb$v_2 <- NULL
  comb$v_3 <- NULL
  comb$imp <- NULL
}

高效优雅的实现方案

方案1:dplyr分组递推填充

利用dplyr分组结合accumulate函数实现递推计算,适合习惯tidyverse语法的场景:

library(dplyr)
library(purrr)

comb_filled <- comb %>%
  group_by(state) %>%
  mutate(
    v = accumulate(v, function(last_val, curr_val) {
      if (is.na(curr_val)) {
        # 取当前位置前三个值的加权和
        prev_2 <- lag(v, n=2)[cur_group_rows()][which(v == last_val)]
        prev_3 <- lag(v, n=3)[cur_group_rows()][which(v == last_val)]
        0.65 * last_val + 0.25 * prev_2 + 0.10 * prev_3
      } else {
        curr_val
      }
    })
  ) %>%
  ungroup()

方案2:data.table高效分组计算

data.table在大分组数据场景下性能更优,适合数据量较大的情况:

library(data.table)
setDT(comb)

comb[, v := {
  len <- .N
  for (k in 4:len) {
    if (is.na(v[k])) {
      v[k] <- 0.65*v[k-1] + 0.25*v[k-2] + 0.10*v[k-3]
    }
  }
  v
}, by = state]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:51:01