如何在R中按最近日期填充NA值(优先locf处理等距情况)
解决方案
通过计算每个NA值到前后最近非NA值的日期距离,动态选择符合规则的填充值,替代固定的两次locf操作。以下是调整后的代码:
调整后代码
library(tidyverse) library(zoo) read.csv("path/to/merged_data.csv", colClasses = c("Date", "numeric", "numeric", "numeric", "character")) %>% group_by(field_id) %>% arrange(date) %>% # 处理NDVI_l8列的填充 mutate( # 生成正向、反向填充的基础值 l8_locf = na.locf(NDVI_l8, na.rm = FALSE), l8_locb = na.locf(NDVI_l8, fromLast = TRUE, na.rm = FALSE), # 获取前后最近非NA值的日期 l8_prev_date = na.locf(date[!is.na(NDVI_l8)], na.rm = FALSE), l8_next_date = na.locf(date[!is.na(NDVI_l8)], fromLast = TRUE, na.rm = FALSE), # 计算到前后非NA值的日期差 dist_prev_l8 = date - l8_prev_date, dist_next_l8 = l8_next_date - date, # 按规则选择填充值:距离相等时优先向前填充 NDVI_l8_filled = case_when( !is.na(NDVI_l8) ~ NDVI_l8, dist_prev_l8 <= dist_next_l8 ~ l8_locf, TRUE ~ l8_locb ) ) %>% # 处理NDVI_s2列,逻辑与NDVI_l8一致 mutate( s2_locf = na.locf(NDVI_s2, na.rm = FALSE), s2_locb = na.locf(NDVI_s2, fromLast = TRUE, na.rm = FALSE), s2_prev_date = na.locf(date[!is.na(NDVI_s2)], na.rm = FALSE), s2_next_date = na.locf(date[!is.na(NDVI_s2)], fromLast = TRUE, na.rm = FALSE), dist_prev_s2 = date - s2_prev_date, dist_next_s2 = s2_next_date - date, NDVI_s2_filled = case_when( !is.na(NDVI_s2) ~ NDVI_s2, dist_prev_s2 <= dist_next_s2 ~ s2_locf, TRUE ~ s2_locb ) ) %>% # 保留NDVI_l7非NA的行,清理中间变量 filter(!is.na(NDVI_l7)) %>% select(-starts_with("l8_"), -starts_with("s2_"), -NDVI_l8, -NDVI_s2) %>% relocate(field_id, .after = last_col()) %>% write_csv(file.path(results, "merged_data_interpolated.csv"))
代码说明
- 先对
NDVI_l8和NDVI_s2分别生成正向、反向填充值,同时计算每个NA值到前后最近非NA值的日期差 - 通过
case_when判断:若当前值非NA则保留原数值;若到前一个非NA值的距离小于等于后一个,使用正向填充值,否则使用反向填充值 - 保留了原有代码的分组、排序、过滤逻辑,风格统一且规则实现更精准
内容的提问来源于stack exchange,提问作者Barbara Perez de Araújo
相关产品推荐
相关产品推荐

