You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于位置条件删除重复行:保留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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:00:34