找到重复的整行并标记单个 R 数据帧内的微小差异的更好方法?

问题描述 投票:0回答:1

我有一个包含近 200,000 行和 20 列的大型数据集(数字和字符串数据的混合)。每行都有一个唯一的标识符。少于 100 行具有重复标识符。我想确定两件事:

  1. 如果具有重复标识符的每一行在所有 20 列或仅某些列中具有完全相同的重复值(标识符至少有 1 列)。
  2. 对于具有重复标识符且所有列中的值不相同的每组行,确定哪些列具有不同的值。

我看过其他几篇 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 分数列和名称列不同。
最好,报告值可以显示为上面重复检查数据框示例中的第三个结果列,但我愿意接受不同的报告选项。
我还没有这部分的代码解决方案。

谢谢!

r dataframe row unique difference
1个回答
0
投票

我推断您只关心将第二行及后续行与第一行进行比较,而不是完整的成对差异集。

这会向原始框架添加一列,提供以逗号分隔的列名称列表。

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(.)
用于与第一行相同的行。有差异的重复。

© www.soinside.com 2019 - 2024. All rights reserved.