基于两个日期对DataFrame去重:按ID保留Date2与Date1最接近的行的实现方法
解决方法:按ID筛选Date2与Date1最接近的行
这问题我熟,咱们一步步来实现,保证每个ID只留一行,且是Date2和Date1日期差最小的那行~
首先要注意:你的Date1和Date2都是字符串格式,得先转换成R能识别的日期类型,不然没法计算日期差。下面给你两种常用的实现方式:
方法一:用dplyr包(推荐,代码更直观)
dplyr是处理数据框的常用工具包,代码逻辑清晰,容易理解:
# 先加载dplyr包,如果没安装先运行install.packages("dplyr") library(dplyr) # 处理数据:转换日期→分组→计算差值→筛选最小差值行→去重 df_processed <- df %>% # 把字符串日期转换成R的日期格式(注意是日/月/年,所以format用"%d/%m/%Y") mutate( Date1 = as.Date(Date1, format = "%d/%m/%Y"), Date2 = as.Date(Date2, format = "%d/%m/%Y") ) %>% # 按ID分组,后续操作都在每个ID组内进行 group_by(ID) %>% # 计算Date2与Date1的绝对日期差(避免正负影响) mutate(date_diff = abs(Date2 - Date1)) %>% # 筛选出每个组中日期差最小的行 filter(date_diff == min(date_diff)) %>% # 如果同一ID有多个行日期差相同,只保留第一行 slice_head(n = 1) %>% # 去掉临时计算的date_diff列 select(-date_diff) %>% # 取消分组,回到普通数据框 ungroup() # 查看结果 print(df_processed)
方法二:用Base R(无需额外加载包)
如果你不想加载第三方包,用Base R也能实现:
# 第一步:转换日期格式 df$Date1 <- as.Date(df$Date1, format = "%d/%m/%Y") df$Date2 <- as.Date(df$Date2, format = "%d/%m/%Y") # 第二步:计算每个行的绝对日期差 df$date_diff <- abs(df$Date2 - df$Date1) # 第三步:找出每个ID组中日期差最小的行的索引 min_diff_idx <- ave(df$date_diff, df$ID, FUN = function(x) x == min(x)) == 1 # 第四步:筛选出这些行,并且每个ID只保留第一行 df_processed <- df[min_diff_idx, ] df_processed <- df_processed[!duplicated(df_processed$ID), ] # 第五步:去掉临时的date_diff列 df_processed$date_diff <- NULL # 查看结果 print(df_processed)
验证结果
运行后你会看到:
- ID=5的行,Date2是
2014-07-22,和Date1完全相同,是最接近的; - ID=14的行,Date2是
2015-05-14,和Date12016-11-08的日期差最小。
内容的提问来源于stack exchange,提问作者Lili
相关产品推荐
相关产品推荐

