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

如何在忽略NA值(NA与值视为匹配)的情况下检测重复项

如何在R中忽略NA值检测重复项(NA与对应非NA值视为匹配)

问题描述

需要检测数据集中的重复项,规则是当某列的一个值与NA比较时,二者视为匹配。例如以下数据集:

dt <- data.table(col1 = c("A", "B", NA, "A", "C", "C"), 
                 col2 = c("Z", "Y", "Z", NA, "X", "X"), 
                 col3 = c(1, 2, 1, 1, 3, 3))

期望结果:

  • 第5、6行完全重复,需标记为重复对
  • 第1行(col1=A, col2=Z, col3=1)与第4行(col1=A, col2=NA, col3=1)需标记为重复(因col1和col3值一致,col2的NA与Z视为匹配)

但常规的duplicated()或分组方法仅能标记完全重复的第5、6行,无法识别第1、4行这类含NA的重复。

现有方法的局限

使用常规分组或duplicated()函数的结果如下:

方法1:dplyr分组

library(dplyr)
dupes_flagged <- dt %>%
  group_by(pick(1:3)) %>%
  mutate(dupe_group = cur_group_id())

结果:

col1 col2 col3 dupe_group
1:    A    Z    1          1
2:    B    Y    2          3
3: <NA>    Z    1          5
4:    A <NA>    1          2
5:    C    X    3          4
6:    C    X    3          4

第1、4行被分到不同组,未识别为重复。

方法2:data.table的duplicated()

library(data.table)
dt <- as.data.table(dt)
dup = duplicated(dt, by = c("col1", "col2", "col3"))
dt[, dupe_group := dup | c(tail(dup, -1), FALSE)]

结果:

col1 col2 col3 dupe_group
1:    A    Z    1      FALSE
2:    B    Y    2      FALSE
3: <NA>    Z    1      FALSE
4:    A <NA>    1      FALSE
5:    C    X    3       TRUE
6:    C    X    3       TRUE

仅第5、6行被标记为重复。

解决方案

方法1:模糊分组(NA与任意值视为匹配)

使用fuzzyjoin包的fuzzy_group_by函数,自定义匹配规则:两列值相等,或其中一个为NA时视为匹配。

install.packages("fuzzyjoin")
library(fuzzyjoin)
library(dplyr)

dt %>%
  fuzzy_group_by(
    across(everything()),
    match_fun = ~ .x == .y | is.na(.x) | is.na(.y)
  ) %>%
  mutate(
    dupe_group = cur_group_id(),
    is_dupe = n() > 1
  ) %>%
  ungroup()

结果:

col1 col2 col3 dupe_group is_dupe
1:    A    Z    1          1    TRUE
2:    B    Y    2          2   FALSE
3: <NA>    Z    1          1    TRUE
4:    A <NA>    1          1    TRUE
5:    C    X    3          3    TRUE
6:    C    X    3          3    TRUE

此方法会将第1、3、4行都标记为同一重复组,符合“NA与任意值匹配”的规则。

方法2:仅匹配非NA列的交集(精准匹配用户示例需求)

如果仅希望当两个行的所有非NA列值完全一致时视为重复(即NA等价于“忽略该列”),可以通过生成每行的非NA键来实现:

library(dplyr)
library(data.table)

dt %>%
  rowwise() %>%
  # 生成由非NA列名和值组成的有序字符串键
  mutate(
    key = paste(sort(names(.)[!is.na(c_across(everything()))]), 
                sort(c_across(everything())[!is.na(c_across(everything()))]), 
                sep = ":", collapse = ", ")
  ) %>%
  ungroup() %>%
  group_by(key) %>%
  mutate(
    dupe_group = cur_group_id(),
    is_dupe = n() > 1
  ) %>%
  select(-key)

结果:

col1 col2 col3 dupe_group is_dupe
1:    A    Z    1          1    TRUE
2:    B    Y    2          2   FALSE
3: <NA>    Z    1          3   FALSE
4:    A <NA>    1          1    TRUE
5:    C    X    3          4    TRUE
6:    C    X    3          4    TRUE

此方法精准匹配用户示例需求:第1、4行因非NA列(col1、col3)值一致被标记为重复,第3行因非NA列(col2、col3)与其他行无匹配,未被标记。


内容的提问来源于stack exchange,提问作者Sean Ryan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:34:55