如何移除R列表中数据框内及框间的_uuid重复行?
解决列表中数据框内及跨数据框的UUID去重问题
问题场景
现有存储数据框的列表my_list,结构如下:
my_list <- list(structure(list("_uuid" = c("xxxyz", "xxxyz", "zzuio", "iiopz"), country = c("USA", "USA", "Canada", "Switzerland")), class = "data.frame", row.names = c(NA, -4L)), structure(list("_uuid" = c("xxxyz", "ppuip", "zzuio"), country = c("USA", "Canada", "Canada")), class = "data.frame", row.names = c(NA, -3L)))
输出结构:
[[1]] _uuid country 1 xxxyz USA 2 xxxyz USA 3 zzuio Canada 4 iiopz Switzerland [[2]] _uuid country 1 xxxyz USA 2 ppuip Canada 3 zzuio Canada
当前使用的代码仅能移除单个数据框内的重复行,无法处理跨数据框的重复:
my_list <- lapply(my_list, function(z) z[!duplicated(z[["_uuid"]]),])
处理后仍存在跨框重复,期望得到如下输出:
[[1]] _uuid country 4 iiopz Switzerland [[2]] _uuid country 1 xxxyz USA 2 ppuip Canada 3 zzuio Canada
需求明确
- 基于
_uuid字段去重,其他字段允许重复 - 无需合并数据框即可完成去重
- 优先保留最后出现的观测(如示例中
zzuio仅保留在第二个数据框) - 适配超100个数据框的场景,仅
_uuid为固定字段 - 去重结果重新赋值给原对象
my_list
解决方案代码
# 1. 先去除每个数据框内部的重复,保留当前框内_uuid最后出现的行 my_list <- lapply(my_list, function(df) { df[!duplicated(df[["_uuid"]], fromLast = TRUE), ] }) # 2. 收集所有_uuid及其最后出现的列表索引位置 uuid_positions <- Map(function(df, idx) { data.frame(_uuid = df[["_uuid"]], list_idx = idx) }, my_list, seq_along(my_list)) %>% do.call(rbind, .) last_occurrence <- tapply(uuid_positions$list_idx, uuid_positions$_uuid, max) # 3. 过滤每个数据框,仅保留该_uuid最后出现位置为当前框的行 my_list <- Map(function(df, idx) { target_uuids <- names(last_occurrence[last_occurrence == idx]) df[df[["_uuid"]] %in% target_uuids, ] }, my_list, seq_along(my_list))
代码说明
- 内部去重:使用
duplicated(..., fromLast = TRUE)确保每个数据框内的重复UUID只保留最后出现的行,避免同一框内的冗余数据干扰后续跨框判断。 - 记录最后出现位置:通过
Map给每个数据框添加索引,合并后用tapply统计每个UUID在整个列表中最后出现的位置索引。 - 跨框过滤:再次遍历每个数据框,只保留那些最后出现位置恰好是当前数据框索引的UUID行,实现跨数据框去重且保留最后出现的观测。
内容的提问来源于stack exchange,提问作者johnjohn
相关产品推荐
相关产品推荐

