计算分组矩阵中唯一值的数量
Calculate number of unique values in grouped matrix
我有一个如下所示的分组数据集:
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 和总结,但我无法将其扩展到这种特殊情况,这需要跨多个列和行检查每个值。例如,n_distinct 本身不起作用,因为我正在寻找非重复值,而不是唯一值。
理想情况下,该解决方案也会忽略 NA,并且不会将它们计为重复值或非重复值。
这里有一个 tidyverse
的选项。使用 pivot_longer
重塑为 'long' 格式,按 '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
在基础 R 中你会做:
a <- tapply(unlist(data[-1]), data$group[row(data[-1])],table)
data$uniq.vals <- c(by(data, seq(nrow(data)),
function(x)sum(a[[x[,1]]][unlist(x[-1])]<2)))
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
请注意,在您的情况下,第 3 行应该有 1,因为只有 I 是唯一值
我有一个如下所示的分组数据集:
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 和总结,但我无法将其扩展到这种特殊情况,这需要跨多个列和行检查每个值。例如,n_distinct 本身不起作用,因为我正在寻找非重复值,而不是唯一值。
理想情况下,该解决方案也会忽略 NA,并且不会将它们计为重复值或非重复值。
这里有一个 tidyverse
的选项。使用 pivot_longer
重塑为 'long' 格式,按 '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
在基础 R 中你会做:
a <- tapply(unlist(data[-1]), data$group[row(data[-1])],table)
data$uniq.vals <- c(by(data, seq(nrow(data)),
function(x)sum(a[[x[,1]]][unlist(x[-1])]<2)))
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
请注意,在您的情况下,第 3 行应该有 1,因为只有 I 是唯一值