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

如何用R的dplyr实现行级样条插值填充数据框NA值?

高效实现tibble行内自然样条插值(替代for循环)

问题背景

现有包含缺失值的tibble,需对每行执行自然样条插值填充NA,但原for循环在15万行数据下效率极低,尝试的dplyr代码无法正常运行。

示例数据:

library(tibble)
df <- tibble(
  column1 = c(1, 5, 10),
  column2 = c(2, NA, 12),
  column3 = c(NA, 7, NA),
  column4 = c(4, 8, 16)
)

原for循环代码(可行但效率低):

num_col <- ncol(df)
x_interp <- seq(1, num_col, 1)

for (idx_row in 1:nrow(df)) {
  df[idx_row, ] <- as.list((spline(x_interp, df[idx_row, ], xout = x_interp, method = "natural")$y))
}

期望输出:

column1 column2 column3 column4
    <dbl>   <dbl>   <dbl>   <dbl>
1       1       2       3       4
2       5       6       7       8
3      10      12      14      16

高效dplyr实现方案

方案1:rowwise + cur_data(易读性优先)

利用rowwise()按行处理,结合cur_data()获取当前行完整向量,避免嵌套across的逻辑错误:

library(dplyr)

num_col <- ncol(df)
x_interp <- seq(1, num_col, 1)

df_filled <- df %>%
  rowwise() %>%
  mutate(
    # 对当前行所有值执行插值,结果存为list列
    interp_result = list(spline(x_interp, cur_data(), xout = x_interp, method = "natural")$y)
  ) %>%
  # 将插值结果映射到每一列
  mutate(across(everything(), ~ interp_result[[which(names(df) == cur_column())]])) %>%
  select(-interp_result) %>%
  ungroup()

方案2:purrr::pmap(性能优先)

使用pmap实现向量化行处理,在大数据量下比rowwise()效率更高:

library(dplyr)
library(tidyr)
library(purrr)

num_col <- ncol(df)
x_interp <- seq(1, num_col, 1)

df_filled <- df %>%
  # 对每行的所有列值执行插值,结果存为list列
  mutate(interp_vals = pmap(., ~ spline(x_interp, c(...), xout = x_interp, method = "natural")$y)) %>%
  # 将list列展开为多列
  unnest_wider(interp_vals) %>%
  # 重命名回原列名
  rename_with(~ names(df), everything())

说明

  • 两种方案均能得到符合预期的插值结果,其中pmap方案在15万行数据下的运行速度远优于原for循环和rowwise()方案
  • 若追求极致性能,可考虑结合data.table实现,但上述方案已完全满足dplyr生态的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:27:39