R语言:按连续NA行数限制填充缺失值的实现需求
解决方案
首先给出你的示例数据:
df1 <- read.table(text = "DT odczyt.1 '2023-08-16 06:57:15' 482.307 '2023-08-16 06:57:30' 482.307 '2023-08-16 06:57:45' 482.311 '2023-08-16 06:58:00' NA '2023-08-16 06:58:15' NA '2023-08-16 06:58:30' 482.315 '2023-08-16 06:58:45' 482.315 '2023-08-16 06:59:00' 482.318 '2023-08-16 06:59:15' 482.324 '2023-08-16 06:59:30' NA '2023-08-16 06:59:45' NA '2023-08-16 07:00:00' NA '2023-08-16 07:00:15' NA '2023-08-16 07:00:30' NA '2023-08-16 07:00:45' NA", header = TRUE)
方法一:分组前向填充(基于dplyr)
通过分组标记连续NA块,判断块长度后决定是否填充:
library(dplyr) df_result <- df1 %>% # 将连续NA与前一个非NA值归为同一组 group_by(grp = cumsum(!is.na(odczyt.1))) %>% mutate( # 计算当前组内连续NA的数量(组总长度减去1个非NA行) na_block_length = n() - 1, # 仅当连续NA数量≤3时,用组内首个非NA值填充 odczyt.1 = ifelse(is.na(odczyt.1) & na_block_length <= 3, first(odczyt.1), odczyt.1) ) %>% ungroup() %>% select(-grp, -na_block_length) print(df_result)
关键逻辑
cumsum(!is.na(odczyt.1))会为每个非NA值生成递增的分组ID,后续连续NA会继承该ID,实现"非NA+后续连续NA"的分组。- 用
na_block_length判断连续NA的数量,仅对≤3的短NA块执行填充,超过3的长NA块保留原NA。
方法二:线性插值填充(基于zoo::na.approx)
如果需要线性插值而非前向填充,可先标记符合条件的NA块,再针对性插值:
library(zoo) library(dplyr) df_result <- df1 %>% mutate( # 标记分组 grp = cumsum(!is.na(odczyt.1)), # 计算组内连续NA的数量 na_block_length = n() - 1, # 标记需要填充的NA need_fill = is.na(odczyt.1) & na_block_length <= 3 ) %>% # 仅对标记的NA执行线性插值,其余保留原数值 mutate(odczyt.1 = ifelse(need_fill, na.approx(odczyt.1, na.rm = FALSE), odczyt.1)) %>% select(-grp, -na_block_length, -need_fill) print(df_result)
关键逻辑
na.approx(..., na.rm = FALSE)会保留未标记的NA,仅对符合条件的短NA块插值,末尾的长NA块会原样保留。
两种方法都能满足你的需求:短NA块被填充,长NA块保留原NA,末尾NA不受影响。
内容的提问来源于stack exchange,提问作者GrBa
相关产品推荐
相关产品推荐

