R语言含impute标记的时间序列DataFrame日期填充实现问询
R语言按规则填充给药数据解决方案
需求说明
处理包含ID、DAY、TIME、AMT的DataFrame,规则如下:
- 每个ID每日应有两条给药记录,对应早晚(约8点、20点)两次给药
- 当
DAY标记为impute且comment_yh值为blue时,填充中间缺失的日期:- 填充的
TIME固定为8:00和20:00 - 保留原始数据中的实际
TIME点 - 填充的
AMT沿用缺失日期前的最近有效剂量
- 填充的
- 若
comment_yh不为blue,则保留原始的impute行不处理
原始数据
df <- data.frame( ID = c(4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6), DAY = c("14/02/2020", "14/02/2020", "15/02/2020", "impute", "18/02/2020", "18/02/2020", "13/02/2020", "impute", "15/02/2020", "15/02/2020", "13/02/2020", "impute", "15/02/2020", "15/02/2020"), TIME = c("8:05", "19:53", "7:45", "NA", "8:10", "20:01", "8:01", "NA", "8:00", "19:50", "8:02", "NA", "8:02", "20:06"), AMT = c(3, 3, 2, NA, 4, 5, 3.5, NA, 3, 4, 2, NA, 1, 2), comment_yh = c(NA, NA, NA, "blue", NA, NA, NA, "blue", NA, NA, NA, "red", NA, NA) )
解决方案代码
使用tidyverse和lubridate包实现,避免复杂循环:
library(tidyverse) library(lubridate) # 数据处理流程 df_processed <- df %>% # 转换日期格式,标记impute行的日期为NA mutate(DAY_date = ifelse(DAY == "impute", NA, dmy(DAY))) %>% group_by(ID) %>% # 标记当前ID是否需要执行填充操作 mutate(need_impute = any(DAY == "impute" & comment_yh == "blue")) %>% ungroup() %>% # 拆分并处理需要填充的ID数据 filter(need_impute) %>% filter(DAY != "impute") %>% group_by(ID) %>% arrange(DAY_date) %>% # 前向填充AMT,确保缺失日期能继承最近有效剂量 fill(AMT, .direction = "down") %>% # 生成完整日期序列,每个日期拆分为两条记录(早晚) complete(DAY_date = seq(min(DAY_date), max(DAY_date), by = "day")) %>% uncount(2) %>% mutate(TIME = rep(c("8:00", "20:00"), n()/2)) %>% # 合并原始数据中的实际TIME和AMT值 left_join( df %>% filter(DAY != "impute") %>% mutate(DAY_date = dmy(DAY)) %>% select(ID, DAY_date, TIME_original = TIME, AMT_original = AMT), by = c("ID", "DAY_date") ) %>% # 替换为原始记录的TIME和AMT(若存在) mutate( TIME = ifelse(!is.na(TIME_original), TIME_original, TIME), AMT = ifelse(!is.na(AMT_original), AMT_original, AMT), DAY = format(DAY_date, "%d/%m/%Y") ) %>% select(ID, DAY, TIME, AMT) %>% ungroup() %>% # 合并不需要填充的ID的原始数据 bind_rows( df %>% filter(!need_impute) %>% select(ID, DAY, TIME, AMT) ) %>% # 按ID、日期、时间排序 arrange(ID, dmy(DAY), TIME) # 查看最终结果 print(df_processed, n = Inf)
关键步骤说明
- 日期转换:用
dmy将字符型日期转为日期格式,方便生成连续日期序列 - 填充标记:通过
any()判断每个ID是否需要执行填充操作 - 完整日期生成:用
complete()生成从最早到最晚的所有日期,uncount(2)为每个日期生成早晚两条记录 - 剂量继承:用
fill()前向填充AMT,保证缺失日期的剂量与最近有效剂量一致 - 原始记录保留:通过左连接合并原始数据的TIME和AMT,替换固定值,保留实际给药时间和剂量
内容的提问来源于stack exchange,提问作者YHO
相关产品推荐
相关产品推荐

