在R语言中替换重复行中匹配日期为对应人员的日期
问题描述
现有如下R数据框,需将其中GrDate列值为6/1/2020(转换为日期类型后为2020-06-01)的记录,替换为同一Nb分组下的其他有效GrDate值:
Nb=100时,将2020-06-01替换为2019-10-20Nb=300时,将2020-06-01替换为2018-07-29Nb=200无匹配目标值,无需处理
原始数据框代码:
# Load required library library(lubridate) # Create the data frame df <- data.frame( Nb = c(100, 100, 200, 200, 300, 300), Name = c("Peter Falk", "PeterFalk", "Chris Jones", "Chris Jones", "Jack Walsh", "Jack Walsh"), GrDate = c("10/20/2019", "6/1/2020", "8/5/2012", "1/7/2024", "6/1/2020", "7/29/2018"), Jdate = c("10/20/2019", "11/26/2023", "8/5/2012", "1/7/2024", "11/26/2023", "3/10/2019"), G = c(76, 76, 83, 85, 76, 76) ) # Convert GrDate and Jdate columns to Date type df$GrDate <- mdy(df$GrDate) df$Jdate <- mdy(df$Jdate)
最优实现方案
以下两种方案均为向量化分组操作,处理高效且逻辑清晰,覆盖边界场景(如分组无有效值时不修改原数据)。
方法1:使用tidyverse(dplyr)
借助dplyr的分组函数,直观实现按Nb替换目标日期:
library(dplyr) df_processed <- df %>% group_by(Nb) %>% mutate( # 提取组内第一个非目标日期的有效值(可根据需求替换为last/min/max等) valid_grdate = first(GrDate[GrDate != mdy("6/1/2020")]), # 替换目标日期为有效值 GrDate = if_else(GrDate == mdy("6/1/2020"), valid_grdate, GrDate) ) %>% ungroup() %>% select(-valid_grdate) # 移除临时辅助列 # 查看处理后结果 print(df_processed)
方法2:使用Base R
无需额外加载包,用ave()函数实现分组替换:
target_date <- mdy("6/1/2020") df$GrDate <- ave(df$GrDate, df$Nb, FUN = function(x) { valid_dates <- x[x != target_date] # 存在有效值则替换,否则保留原数据 if (length(valid_dates) > 0) { replace(x, x == target_date, valid_dates[1]) } else { x } }) # 查看处理后结果 print(df)
方案说明
- 两种方法均为向量化操作,比循环遍历效率更高,适合处理大数据集;
- 若分组内存在多个有效值,可将
first()替换为last()、min()或max(),按需选择合适的有效值; - 自动兼容分组无有效值的场景,不会产生报错,原数据保持不变。
内容的提问来源于stack exchange,提问作者user3482393
相关产品推荐
相关产品推荐

