基于两列去重并保留最新created_at记录的R语言实现
问题:按分组保留最新记录
现有R语言数据框,其中year(整数型)与legal_entity_registration_number(整数型)构成的组合存在重复记录,需依据created_at(日期时间格式)字段,保留每组重复数据中最新的一条完整记录。使用duplicated()函数仅能筛选重复观测,无法直接实现保留全列并提取最新记录的需求,以下是原始数据、期望结果及可行解决方案。
原始数据框
df <- structure(list( file_id = c(20045467L, 20057886L, 21624801L, 21624810L, 14889735L, 14889737L), legal_entity_registration_number = c(40003032949, 40003032949, 40003032949, 40003032949, 40003032949, 40003032949), year = c(2017L, 2017L, 2018L, 2018L, 2008L, 2008L), employees = c(1431L, 3908L, 1355L, 3508L, 1380L, 5378L), currency = c("EUR", "EUR", "EUR", "EUR", "LVL", "LVL"), rounded_to_nearest = c("THOUSANDS", "THOUSANDS", "THOUSANDS", "THOUSANDS", "ONES", "ONES"), created_at = structure(c(1604730505, 1604732566, 1605357231, 1605357235, 1597335737, 1609340436), class = c("POSIXct", "POSIXt"), tzone = "") ), row.names = c(NA, 6L), class = "data.frame")
期望结果数据框
expected_df <- structure(list( file_id = c(14889737L, 20057886L, 21624810L), legal_entity_registration_number = c(40003032949, 40003032949, 40003032949), year = c(2008L, 2017L, 2018L), employees = c(5378L, 3908L, 3508L), currency = c("LVL", "EUR", "EUR"), rounded_to_nearest = c("ONES", "THOUSANDS", "THOUSANDS"), created_at = structure(c(1609340436, 1604732566, 1605357235), tzone = "", class = c("POSIXct", "POSIXt")) ), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -3L), groups = structure(list( year = c(2008L, 2017L, 2018L), legal_entity_registration_number = c(40003032949, 40003032949, 40003032949), .rows = structure(list(1L, 2L, 3L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list")) ), row.names = c(NA, -3L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE))
可行解决方案
方法1:使用tidyverse(dplyr)
这是最直观的方案,通过分组+排序+取首行实现:
library(dplyr) result_df <- df %>% # 按分组列分组 group_by(year, legal_entity_registration_number) %>% # 按created_at降序排列,最新记录排在每组最前面 arrange(desc(created_at), .by_group = TRUE) %>% # 取每组第一行 slice_head(n = 1) %>% # 可选:取消分组(如果不需要保留分组属性) ungroup()
或者更简洁的写法,直接用slice_max取每组最大的created_at对应的行:
result_df <- df %>% group_by(year, legal_entity_registration_number) %>% slice_max(created_at, n = 1) %>% ungroup()
方法2:使用Base R
无需加载额外包,通过排序+去重实现:
# 先按分组列升序,再按created_at降序排序 sorted_df <- df[order(df$year, df$legal_entity_registration_number, -df$created_at), ] # 保留每组的第一条记录(即最新记录),去掉后续重复的分组组合 result_df <- sorted_df[!duplicated(sorted_df[c("year", "legal_entity_registration_number")]), ]
两种方法都能得到与期望结果一致的输出,保留所有列且仅保留每组最新记录。
内容的提问来源于stack exchange,提问作者Ricards Agapovs
相关产品推荐
相关产品推荐

