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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:32:05