在R中定位时间序列列内部缺失值,并用同时间步其他序列均值填充
仅填充时间序列DataFrame的内部缺失值
需求说明
给定一个以列为时间序列、行为时间步的DataFrame,需要:
- 仅填充每个时间序列(列)中的内部缺失值(即被非NA值前后包围的NA,排除列首尾的连续NA块)
- 填充值取同一时间步(行)下其他时间序列的可用值的均值
示例数据
test <- data.frame( "ts1" = c(1, 1, 1, NA, 1, 1, NA, 1, 1, 1), "ts2" = c(NA, NA, 2, 2, 2, 2, NA, 2, NA, NA), "ts3" = c(NA, NA, NA, 3, 3, 3, 3, 3, NA, 3) )
例如ts1第4行的NA属于内部缺失值,应替换为(2 + 3)/2 = 2.5。
你的代码问题点
你编写的fixie函数未生效,核心问题如下:
- 赋值错误:最后一步使用
==比较运算符而非<-赋值,导致DataFrame未被修改 - 内部缺失值识别逻辑错误:循环逻辑无法正确覆盖所有内部NA场景(比如单个内部NA、连续内部NA)
- 无返回值:函数未返回修改后的
df,调用后无法获取结果 - 位置存储混乱:用
tofill[i]存储NA位置会导致索引错位,无法准确记录每列的目标位置
解决方案
方法1:基础R实现(逻辑清晰)
先明确内部缺失值的判定规则:某位置为NA,且处于该列第一个非NA值和最后一个非NA值之间。基于此实现填充:
fix_internal_na <- function(df) { for (col_idx in seq_along(df)) { col_data <- df[[col_idx]] na_pos <- which(is.na(col_data)) if (length(na_pos) == 0) next # 确定当前列的有效范围(第一个和最后一个非NA的位置) first_non_na <- min(which(!is.na(col_data))) last_non_na <- max(which(!is.na(col_data))) # 筛选出需要填充的内部NA位置 target_rows <- na_pos[na_pos > first_non_na & na_pos < last_non_na] # 逐行填充:取当前行其他列的均值 for (row_idx in target_rows) { df[row_idx, col_idx] <- mean(df[row_idx, -col_idx], na.rm = TRUE) } } return(df) } # 测试函数 fixed_test <- fix_internal_na(test) print(fixed_test)
方法2:tidyverse风格(简洁高效)
利用dplyr和tidyr的向量化操作,代码更简洁:
library(dplyr) library(tidyr) fixed_test <- test %>% rowwise() %>% # 计算每行除当前列外的均值(临时辅助列) mutate(row_mean = mean(c_across(-cur_column()), na.rm = TRUE)) %>% ungroup() %>% # 遍历每列填充内部NA mutate(across(everything(), ~{ first_non_na <- min(which(!is.na(.x))) last_non_na <- max(which(!is.na(.x))) ifelse( is.na(.x) & row_number() > first_non_na & row_number() < last_non_na, row_mean, .x ) })) %>% select(-row_mean) print(fixed_test)
结果验证
两种方法处理后的核心结果一致:
ts1第4行NA → 2.5,第7行NA → 3(仅ts3有有效值)ts2第7行NA → 2(ts1和ts3有效值的均值)ts3第9行NA → 1(仅ts1有有效值)
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

