在R中基于ID匹配最邻近日期并创建新数据框的实现
我来帮你搞定这个按ID匹配最邻近日期的需求!下面分别用dplyr和data.table两种常用工具实现,先看我们的示例数据:
示例数据
首先把你的示例数据转换成R可识别的格式:
# Dataframe A df_a <- data.frame( ID = c(3,5,8,1,1,1), DATE_A = c("15/05/06", "14/11/05", "25/11/08", "16/12/10", "5/01/12", "24/07/14") ) # Dataframe B df_b <- data.frame( ID = c(3,3,5,5,5,8,8,8,8,1,1,1,1,1), DATE_B = c("12/12/05", "17/04/06", "25/07/05", "26/09/05", "1/12/05", "12/09/08", "13/11/08", "23/12/08", "31/03/09", "26/11/10", "12/08/11", "12/11/11", "14/03/14", "8/08/14") )
第一步必须先把字符型的日期转换成R的Date类型,否则没法计算日期差:
# 转换日期格式(注意是dd/mm/yy格式) df_a$DATE_A <- as.Date(df_a$DATE_A, format = "%d/%m/%y") df_b$DATE_B <- as.Date(df_b$DATE_B, format = "%d/%m/%y")
方法一:使用dplyr包
我们可以通过按ID左连接,然后计算日期差的绝对值,最后分组筛选出差值最小的记录:
library(dplyr) result_dplyr <- df_a %>% # 按ID左连接,把同ID的所有DATE_B都匹配过来 left_join(df_b, by = "ID") %>% # 计算两个日期的绝对差值 mutate(date_diff = abs(DATE_A - DATE_B)) %>% # 按ID和DATE_A分组,筛选出差值最小的行(如果有多个相同最小差值会保留所有) group_by(ID, DATE_A) %>% slice_min(order_by = date_diff, n = 1, with_ties = TRUE) %>% # 去掉不需要的差值列,整理结果 ungroup() %>% select(ID, DATE_A, DATE_B) # 查看结果 print(result_dplyr)
方法二:使用data.table包
data.table的写法更高效,适合处理大数据量,思路类似但语法更简洁:
library(data.table) # 转换成data.table格式 setDT(df_a) setDT(df_b) # 实现匹配逻辑 result_dt <- df_a[df_b, on = "ID", allow.cartesian = TRUE][, date_diff := abs(DATE_A - DATE_B)][, .SD[date_diff == min(date_diff)], by = .(ID, DATE_A)][, !"date_diff"] # 查看结果 print(result_dt)
结果示例
两种方法都会得到类似这样的输出(日期显示为R的标准Date格式):
ID DATE_A DATE_B 1: 3 2006-05-15 2006-04-17 2: 5 2005-11-14 2005-12-01 3: 8 2008-11-25 2008-11-13 4: 1 2010-12-16 2010-11-26 5: 1 2012-01-05 2011-11-12 6: 1 2014-07-24 2014-08-08
内容的提问来源于stack exchange,提问作者sar
相关产品推荐
相关产品推荐

