我有一个包含近 200,000 行和 20 列的大型数据集(数字和字符串数据的混合)。每行都有一个唯一的标识符。少于 100 行具有重复标识符。我想确定两件事:
我看过其他几篇 SO 帖子,但他们通常按列而不是行讨论重复项和/或跨数据帧而不是在数据帧内进行比较。
这是一个小数据示例。
请注意,有 org_id 值 (a,b,c),其中 a 和 b 是重复的。对于 org_id a,列中的所有值都是重复的,但对于 org_id b 则不是。
# load toy data
df <- data.frame(org_id=c("a","a","b","b","b","c"),
thing=c("1","1","1","1","2","1"),
name=c("really_long_A_name_here", "really_long_A_name_here", "really_long_B_name_here", "really_long_B2_name_here", "really_long_B_name_here", "really_long_C_name_here"),
start=c("2020-10-31", "2020-10-31", "2022-09-17", "2022-09-17", "2022-09-17", "2023-05-11") )
df
org_id | 分数 | 名字 | 开始 |
---|---|---|---|
a | 1 | 这里真的很长一个名字 | 2020-10-31 |
a | 1 | 这里真的很长一个名字 | 2020-10-31 |
b | 1 | 这里是really_long_B_name | 2022-09-17 |
b | 1 | really_long_B2_name_here | 2022-09-17 |
b | 2 | 这里是really_long_B_name | 2022-09-17 |
c | 1 | really_long_C_name_here | 2023-05-11 |
这是我需要的示例: 首先,另一个数据框告诉我哪个 org_id 有重复的行值,例如:
exact_dup | dup_orgs |
---|---|
正确 | a |
错误 | b |
至此,我将行数据组合成一长串进行比较。 下面的代码可以工作,但看起来很笨拙。关于如何改进这个问题有什么建议吗?
# create a long string for each row
df$x <- apply(df, 1, paste0, collapse="|")
# placeholder dataframe to identify which uplicate rows in the data are exact duplicates across the entire row
review_dups <- data.frame(exact_dup = NA, dup_orgs = df |> filter(duplicated(org_id)==TRUE) |> distinct(org_id)|> pull(org_id) )
# loop to find differences
for(i in 1:nrow(review_dups)){
n <- df |> filter(org_id == review_dups$dup_orgs[i]) |> select(x) |> count(x) |> pull(n) |> max()
dup_rows <- df |> filter(org_id == review_dups$dup_orgs[i]) |> nrow()
review_dups[i,1] <- n==dup_rows
rm(n, dup_rows)
}
rm(i)
# view results
review_dups
其次,我需要一种方法来报告那些与具有重复 org_id 的行的其余行不匹配的数据列。
因此,输出应该告诉我 org_id b 分数列和名称列不同。
最好,报告值可以显示为上面重复检查数据框示例中的第三个结果列,但我愿意接受不同的报告选项。
我还没有这部分的代码解决方案。
谢谢!
我推断您只关心将第二行及后续行与第一行进行比较,而不是完整的成对差异集。
这会向原始框架添加一列,提供以逗号分隔的列名称列表。
df$dupe_differences <- unlist(by(df, df$org_id, function(dat) {
if (nrow(dat) == 1) return(NA)
c("", sapply(2:nrow(dat), function(i) {
same <- mapply(Negate(`%in%`), dat[1,], dat[i,])
paste(names(same[same]), collapse = ",")
}))
}))
df
# org_id thing name start dupe_differences
# 1 a 1 really_long_A_name_here 2020-10-31
# 2 a 1 really_long_A_name_here 2020-10-31
# 3 b 1 really_long_B_name_here 2022-09-17
# 4 b 1 really_long_B2_name_here 2022-09-17 name
# 5 b 2 really_long_B_name_here 2022-09-17 thing
# 6 c 1 really_long_C_name_here 2023-05-11 <NA>
区别是明确的:
NA
表示没有重复项,该行是唯一的""
(空字符串)意味着其内容与该复制集的第一行相同从这里,您可以使用
is.na(.)
(用于无重复)轻松过滤出所需的特定行,!is.na(.) & !nzchar(.)
用于与第一行(包括第一行)相同的行,!is.na(.) & nzchar(.)
用于与第一行相同的行。有差异的重复。