基于位置条件删除重复行:保留id/year组最后一条观测
嗨,这个需求在R里有好几种简单的实现方式,我给你分享几个常用的方案,都能精准得到你想要的结果:
首先先把你的原始数据集贴出来方便参考:
df <- data.frame( "id" = c("Alpha", "Alpha", "Alpha","Alpha","Beta","Beta","Beta","Beta"), "Year" = c(1970,1970,1970,1971,1980,1980,1981,1982), "Val" = c(2,3,-2,5,2,5,3,5) )
方法1:用dplyr(tidyverse生态)实现(推荐)
这个方法逻辑清晰,代码可读性很高,是日常处理这类分组筛选需求的常用方式:
library(dplyr) final <- df %>% group_by(id, Year) %>% # 按id和Year分组 slice_tail(n = 1) %>% # 提取每组的最后一行观测 ungroup() # 取消分组状态,恢复普通数据框结构 # 查看最终结果 final
slice_tail(n=1)会直接取每个分组的最后一条记录,完美匹配你的需求。
方法2:Base R原生实现(无需额外包)
如果你不想加载第三方包,用Base R也能轻松搞定,这里给你两种写法:
写法A:利用ave函数筛选行
# 先给每行添加行号,标记原始顺序 df$row_index <- seq(nrow(df)) # 按id和Year分组,找出每组中最大的行号(也就是最后一行的位置) final <- df[ave(df$row_index, df$id, df$Year, FUN = max) == df$row_index, ] # 移除临时添加的行号列 final <- final[, !names(final) == "row_index"]
写法B:拆分+合并的思路
# 把数据按id和Year拆分成多个子数据框 grouped_data <- split(df, list(df$id, df$Year)) # 对每个子数据框取最后一行,再合并成最终数据框 final <- do.call(rbind, lapply(grouped_data, tail, n = 1)) # 可选:重置行名,让结果更整洁 rownames(final) <- NULL
以上几种方法运行后,得到的结果都会和你期望的final数据集完全一致。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

