使用R的tidyverse筛选big_df中ID对应日期早于且最接近small_df的记录
用tidyverse筛选匹配ID的最近历史记录
现有两个包含小鼠ID与日期的数据集big_df和small_df,要求用tidyverse风格编写代码,针对small_df中的每个ID,筛选big_df里日期早于该ID对应small_df日期且最接近的记录,最终输出包含ID、对应日期及value字段的big_df子集。
示例数据集代码
library(tidyverse) # 构建big_df:每个ID对应5条连续日期的记录 big_df <- tibble( ID = rep(1:10, each = 5), date = rep(seq(as.Date("2022-01-01"), as.Date("2022-01-05"), by = "days"), 10), value = sample(15:25, 50, replace = TRUE) ) # 构建small_df:包含8个ID的目标日期 small_df <- tibble( ID = 1:8, date = c("2022-01-05", "2022-01-04", "2022-01-03", "2022-01-02", "2022-01-01", "2022-01-05", "2022-01-04", "2022-01-03") ) %>% mutate(date = as.Date(date))
核心解决方案代码
# 筛选符合要求的记录 result <- big_df %>% # 按ID关联两个数据集,区分两个日期字段 inner_join(small_df, by = "ID", suffix = c("_big", "_small")) %>% # 只保留big_df中日期早于对应small_df日期的记录 filter(date_big < date_small) %>% # 计算两个日期的差值(正数表示big日期更早) mutate(date_diff = date_small - date_big) %>% # 按ID分组,取每组中日期差最小的那条(即最接近目标日期的历史记录) group_by(ID) %>% slice_min(date_diff, n = 1, with_ties = FALSE) %>% ungroup() %>% # 整理输出字段名 select(ID, date = date_big, value) # 查看结果 print(result)
关键逻辑说明
inner_join:只保留两个数据集共有的ID(即small_df中的1-8号),自动排除big_df中不存在于small_df的IDfilter(date_big < date_small):严格筛选出big_df中早于目标日期的记录,排除等于或晚于的情况slice_min(date_diff, n=1, with_ties=FALSE):按ID分组后,取每组中日期差最小的单条记录;如果存在多条相同最小差值的记录,with_ties=FALSE会只取第一条(若需保留所有可去掉该参数)- 最终通过
select整理输出所需的字段,确保结果格式符合要求
内容的提问来源于stack exchange,提问作者microbe
相关产品推荐
相关产品推荐

