利用星期序号填充日期列缺失值的技术问询
问题
我有一个长格式数据集,每个研究对象(subject)一周内被观测5次。数据集包含三列:case(研究对象编号)、day(观测的星期序号)、date(实际观测日期,存在缺失值)。需要利用day的序号信息填充date列的缺失值,示例数据集如下:
df <- data.frame(case = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2), day = c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5), date = as.Date(c("2023-01-02", "2023-01-03", NA, NA, "2023-01-06", NA, "2021-05-11", "2021-05-12", "2021-05-13", NA))) df # case day date # 1 1 2023-01-02 # 1 2 2023-01-03 # 1 3 <NA> # 1 4 <NA> # 1 5 2023-01-06 # 2 1 <NA> # 2 2 2021-05-11 # 2 3 2021-05-12 # 2 4 2021-05-13 # 2 5 <NA>
期望输出:
# case day date #1 1 1 2023-01-02 #2 1 2 2023-01-03 #3 1 3 2023-01-04 #4 1 4 2023-01-05 #5 1 5 2023-01-06 #6 2 1 2021-05-10 #7 2 2 2021-05-11 #8 2 3 2021-05-12 #9 2 4 2021-05-13 #10 2 5 2021-05-14
解决方案
方法一:使用tidyverse工具链
核心思路是按case分组,通过已知日期与对应day的关系推算基准日期,再填充缺失值:
library(dplyr) library(tidyr) df_filled <- df %>% group_by(case) %>% # 计算当前day与组内最小day的差值 mutate(day_offset = day - min(day)) %>% # 提取组内第一个非NA日期作为基准 mutate(base_date = first(date[!is.na(date)])) %>% # 计算基准日期对应的day偏移量 mutate(base_offset = day_offset[!is.na(date)][1]) %>% # 推导填充后的日期 mutate(date = coalesce(date, base_date + (day_offset - base_offset))) %>% # 移除辅助列 select(-day_offset, -base_date, -base_offset) %>% ungroup() print(df_filled)
方法二:使用base R实现
无需额外包,通过循环处理每个研究对象组:
# 遍历每个唯一的研究对象 for (case_id in unique(df$case)) { group_data <- df[df$case == case_id, ] # 获取组内有效的日期和对应day valid_idx <- !is.na(group_data$date) valid_date <- group_data$date[valid_idx][1] valid_day <- group_data$day[valid_idx][1] # 计算基准日期:有效日期 - (有效day - 组内最小day) base_date <- valid_date - (valid_day - min(group_data$day)) # 填充缺失的日期 group_data$date[is.na(group_data$date)] <- base_date + (group_data$day[is.na(group_data$date)] - min(group_data$day)) # 替换回原数据集 df[df$case == case_id, ] <- group_data } print(df)
两种方法均基于同一研究对象的观测日期与day序号呈连续递增1天的规律,通过已知的日期-day对应关系推导基准点,完成缺失值填充。
内容的提问来源于stack exchange,提问作者Michael Matta
相关产品推荐
相关产品推荐

