首页 > 解决方案 > 识别允许 x 不匹配并忽略 NA 的重复行

问题描述

我有一个问题或实际上 2 个相关的问题。

我有一个数据框(行> 10.000,列> 100)。我想识别重复的行。我熟悉duplicated() 和unique()。但是,这些只会找到完全相同的重复项。因此,如果我有一个包含 3 个值的行,1 5 8则不会将其视为具有这些值的行的副本1 NA 8

第一个问题是,我怎样才能找到重复的行但忽略 NA/将 NA 视为通配符?理想情况下,我会创建这些重复行的组。

以以下示例数据为例:

df <- data.frame("x" = c(1,2,2,1,2,1,7,1), 
                 "y"=c(5,3,3,NA,NA,5,8,5), 
                 "z" =  c(8,8,8,8,8,8,9,NA))

df  
  x  y  z  
---------
1 1  5  8  
2 2  3  8  
3 2  3  8  
4 1 NA  8  
5 2 NA  8  
6 1  5  8  
7 1  8  8  
8 1  5 NA  

我意识到忽略 NA 会导致一些问题。例如,我们在第 1 行:1 5 8 和在第 7 行:1 8 8。我们将在哪里分组第 4 行:1 NA 8?它可以与第 1 行和第 4 行匹配,因此属于任一组。所以也许解决这个问题的一种方法是复制第 4 行并分配两个组。我希望这是有道理的...

所以结果是:

  x  y  z group
---------------
1 1  5  8     1
2 2  3  8     2
3 2  3  8     2
4 1 NA  8     1
5 1 NA  8     3
6 2 NA  8     2
7 1  5  8     1
8 1  8  8     3
9 1  5 NA     1

我的第二个问题是,我怎样才能允许 1 个(或更多)不匹配?如果我允许 1 个潜在的不匹配,第 7 行:1 8 8 将与第 1 行:1 5 8 组合在一起

所以结果是:

  x  y  z group
---------------
1 1  5  8     1
2 2  3  8     2
3 2  3  8     2
4 1 NA  8     1
5 1 NA  8     2
6 2 NA  8     1
7 2 NA  8     2
8 1  5  8     1
9 1  8  8     1
10 1  5 NA     1

我意识到这很快就会变得非常棘手,但我仍然希望你能在路上帮助我!

ps 我对 tidyverse 很熟悉,所以包含它的解决方案也很好!

标签: r

解决方案


您可以使用基本 R 函数完成所有这些事情

sum并且all可以使用以下方法处理这样的事情na.rm = TRUE

vec1 <- c(1, 5, 8)
vec2 <- c(1, NA, 8)
vec3 <- c(1, 11, 8)

vec1 == vec2
#> [1] TRUE   NA TRUE

# Compare vectors, ignoring missing values
all(vec1 == vec2, na.rm = TRUE)
#> [1] TRUE
all(vec1 == vec3, na.rm = TRUE)
#> [1] FALSE

# Counting mismatches, checking they're below a threshold
sum(vec1 != vec2, na.rm = TRUE)
#> [1] 0
sum(vec1 != vec3, na.rm = TRUE)
#> [1] 1
sum(vec1 != vec3, na.rm = TRUE) <= 1
#> [1] TRUE

reprex 包(v0.3.0)于 2021-01-21 创建

请注意,在后一种情况下,您正在计算不匹配并忽略NAs。要计算两者,您需要sum(vec1 != vec3, is.na(vec1 == vec3), na.rm = TRUE)

将每一行与其他每一行进行比较

您可以使用嵌套apply将每一列与其他每一列进行比较,返回一个(功能上)三角矩阵,该矩阵为匹配项编制索引

df <- data.frame(v1 = c(1,1, 1,NA,5,1),
                 v2 = c(2,NA,1,NA,1,2),
                 v3 = c(3,3, 1,NA,3,8),
                 v4 = c(4,4, 4,NA,4,4))

df
#>   v1 v2 v3 v4
#> 1  1  2  3  4
#> 2  1 NA  3  4
#> 3  1  1  1  4
#> 4 NA NA NA NA
#> 5  5  1  3  4
#> 6  1  2  8  4


apply(df, 1, function(x){
  apply(df, 1, function(y){
    sum(x != y, na.rm = TRUE) <=1
  })
}) -> matchMatrix

matchMatrix[upper.tri(matchMatrix)] <- NA 

matchMatrix
#>       [,1] [,2]  [,3] [,4]  [,5] [,6]
#> [1,]  TRUE   NA    NA   NA    NA   NA
#> [2,]  TRUE TRUE    NA   NA    NA   NA
#> [3,] FALSE TRUE  TRUE   NA    NA   NA
#> [4,]  TRUE TRUE  TRUE TRUE    NA   NA
#> [5,] FALSE TRUE FALSE TRUE  TRUE   NA
#> [6,]  TRUE TRUE FALSE TRUE FALSE TRUE

reprex 包(v0.3.0)于 2021 年 1 月 28 日创建


推荐阅读