如何在R数据框中筛选时间更早的重复行?
高效筛选重复行并保留日期更早记录的Base R无循环方案
需求:从数据框中按var1列识别重复行,对每个重复的var1组,保留EndDate时间更早的行;非重复的var1行也全部保留。原实现用了for循环,现寻求更高效的Base R无循环方案。
原始数据
data <- structure(list(var1 = c("11", "11", "12", "12", "13", "13", "14", "14", "15", "16" ), EndDate = structure(c(1588792540, 1588942766, 1589118458, 1589059900, 1588669654, 1588979219, 1588876217, 1588786020, 1588506698, 1588512011), class = c("POSIXct", "POSIXt"), tzone = "UTC")), row.names = c(NA, 10L), class = "data.frame")
方案1:用ave()实现(最简洁)
# 按var1分组,筛选每组中EndDate最早的行 newdf <- data[ave(as.numeric(data$EndDate), data$var1, FUN = function(x) x == min(x)) == 1, ]
逻辑说明:
ave()是Base R的分组计算函数,按var1对EndDate(转成数值型方便比较)分组处理- 每组内判断当前行的
EndDate是否等于该组的最小值(即最早日期),生成逻辑向量 - 用这个向量筛选数据框,自动保留非重复组的唯一行,以及重复组中日期最早的行
方案2:用split()+lapply()实现(逻辑更直观)
# 拆分数据组→每组取日期最早行→合并结果 newdf2 <- do.call(rbind, lapply(split(data, data$var1), function(df) { df[which.min(df$EndDate), ] })) # 重置行名(可选,避免分组后行名带组标识) rownames(newdf2) <- NULL
逻辑说明:
split(data, data$var1)把数据按var1拆分成多个子数据框的列表- 遍历每个子数据框,用
which.min()找到EndDate最小的行索引,提取该行 - 最后用
rbind合并所有子结果,得到最终数据框
两种方案都完全避免了for循环,利用Base R的向量/分组运算特性,在数据量大时效率远高于循环实现。
内容的提问来源于stack exchange,提问作者in2td
相关产品推荐
相关产品推荐

