首页 > 解决方案 > 计算分组矩阵中唯一值的数量

问题描述

我有一个如下所示的分组数据集:

data = data.frame(group = c(1,1,1,1,2,2,2,2), 
                  c1 = c("A", "E", "A", "J", "L", "M", "L", "J"), 
                  c2 = c("B", "F", "F", "K", "B", "F", "T", "E"), 
                  c3 = c("C", "G", "C", "L", "C", "X", "C", "V"), 
                  c4 = c("D", "H", "I", "M", "D", "T", "I", "W"))

我需要计算每行中每个组中不重复的值的数量。例如,看起来像这样的东西:

    group c1 c2 c3 c4 uniq.vals
1     1  A  B  C  D         2
2     1  E  F  G  H         3
3     1  A  F  C  I         1
4     1  J  K  L  M         4
5     2  L  B  C  D         2
6     2  M  F  X  T         3
7     2  L  T  C  I         1
8     2  J  E  V  W         4

第 1 行的计数为 2,因为 B 和 D 不会出现在第 1 组中的任何其他行中。

我熟悉使用 group_by 和 summarise,但我无法将其扩展到这种特殊情况,这需要跨多列和多行检查每个值。例如, n_distinct 本身不起作用,因为我正在寻找非重复值,而不是唯一值。

理想情况下,该解决方案还将忽略 NA 并且不将它们视为重复值或非重复值。

标签: rdplyrunique

解决方案


这是一个选项tidyverse。重塑为'long'格式pivot_longer,按'group'分组,replace所有duplicate'value'为NA,然后按行号分组,summarise以获取计数n_distinct(不同元素的数量),并与原始数据绑定

library(dplyr)
library(tidyr)
data %>%
    mutate(rn = row_number()) %>%
    pivot_longer(cols = starts_with('c')) %>% 
    group_by(group) %>%
    mutate(value = replace(value, duplicated(value)|duplicated(value,
     fromLast = TRUE), NA)) %>%
    group_by(rn) %>%
    summarise(uniq.vals = n_distinct(value, na.rm = TRUE), .groups = 'drop') %>%
    select(uniq.vals) %>%
    bind_cols(data, .)

-输出

#   group c1 c2 c3 c4 uniq.vals
#1     1  A  B  C  D         2
#2     1  E  F  G  H         3
#3     1  A  F  C  I         1
#4     1  J  K  L  M         4
#5     2  L  B  C  D         2
#6     2  M  F  X  T         3
#7     2  L  T  C  I         1
#8     2  J  E  V  W         4

推荐阅读