获取每行最频繁的值并考虑关系
Get the most frequent value per row and account for ties
示例数据:
df <- data.frame("ID" = 1:6,
"Group1" = c("A", NA, "C", NA, "E", "C"),
"Group2" = c("E", "C", "C", NA, "E", "E"),
"Group3" = c("A", "A", NA, NA, "C", NA),
"Group4" = c(NA, "C", NA, "D", "C", NA),
"Group5" = c("A", "D", NA, NA, NA, NA))
在每一行中,我想计算每个值的数量并将最频繁出现的值存储在一个新变量中,New.Group
。如果出现平局,则应选择行中的第一个值。应用于示例的逻辑:
New.Group
的第 1 行取值 A
,因为它是该行中出现频率最高的值,忽略 NA
s。
第 2 行取值 C
,因为它也是出现频率最高的值。
第 3 行与第 2 行相同。
第 4 行取值 D
,因为它是该行中唯一的值。
在第 5 行中,E
和 C
都有计数 2,但选择了 E
,因为它在行中的 C
之前遇到。
第6行,与第5行类似,C
和E
的计数都是1,但选择C
是因为在该行的E
之前遇到.
期望的输出:
ID Group1 Group2 Group3 Group4 Group5 New.Group
1 1 A E A <NA> A A
2 2 <NA> C A C D C
3 3 C C <NA> <NA> <NA> C
4 4 <NA> <NA> <NA> D <NA> D
5 5 E E C C <NA> E
6 6 C E <NA> <NA> <NA> C
我认为这可以满足您的需求。对于每一行,它会创建每个字母的 table 频率并选择最大的,同时保留并列的列顺序。然后 returns 这个 table.
中第一列的名称
感谢 Henrik 提出的改进建议。
df$New.Group <- apply(df[-1], 1, function(x) {
names(which.max(table(factor(x, unique(x)))))
})
df
#> ID Group1 Group2 Group3 Group4 Group5 New.Group
#> 1 1 A E A <NA> A A
#> 2 2 <NA> C A C D C
#> 3 3 C C <NA> <NA> <NA> C
#> 4 4 <NA> <NA> <NA> D <NA> D
#> 5 5 E E C C <NA> E
#> 6 6 C E <NA> <NA> <NA> C
使用 dplyr
和 vctrs
的一个选项(利用 vec_count()
中的 location
参数,“按第一次看到键的位置排序”)可以是:
df %>%
rowwise() %>%
mutate(New.Group = na.omit(vec_count(c_across(starts_with("Group")), "location")) %>%
slice_max(count, with_ties = FALSE) %>%
pull(key))
ID Group1 Group2 Group3 Group4 Group5 New.Group
<int> <fct> <fct> <fct> <fct> <fct> <fct>
1 1 A E A <NA> A A
2 2 <NA> C A C D C
3 3 C C <NA> <NA> <NA> C
4 4 <NA> <NA> <NA> D <NA> D
5 5 E E C C <NA> E
6 6 C E <NA> <NA> <NA> C
或者:
df %>%
rowwise() %>%
mutate(New.Group = names(which.max(with(na.omit(vec_count(c_across(starts_with("Group")), "location")), setNames(count, key)))))
我们可以使用Mode
函数
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
df$New.Group <- apply(df[-1], 1, FUN = function(x) Mode(na.omit(x)))
df$New.Group
#[1] "A" "C" "C" "D" "E" "C"
示例数据:
df <- data.frame("ID" = 1:6,
"Group1" = c("A", NA, "C", NA, "E", "C"),
"Group2" = c("E", "C", "C", NA, "E", "E"),
"Group3" = c("A", "A", NA, NA, "C", NA),
"Group4" = c(NA, "C", NA, "D", "C", NA),
"Group5" = c("A", "D", NA, NA, NA, NA))
在每一行中,我想计算每个值的数量并将最频繁出现的值存储在一个新变量中,New.Group
。如果出现平局,则应选择行中的第一个值。应用于示例的逻辑:
New.Group
的第 1 行取值 A
,因为它是该行中出现频率最高的值,忽略 NA
s。
第 2 行取值 C
,因为它也是出现频率最高的值。
第 3 行与第 2 行相同。
第 4 行取值 D
,因为它是该行中唯一的值。
在第 5 行中,E
和 C
都有计数 2,但选择了 E
,因为它在行中的 C
之前遇到。
第6行,与第5行类似,C
和E
的计数都是1,但选择C
是因为在该行的E
之前遇到.
期望的输出:
ID Group1 Group2 Group3 Group4 Group5 New.Group
1 1 A E A <NA> A A
2 2 <NA> C A C D C
3 3 C C <NA> <NA> <NA> C
4 4 <NA> <NA> <NA> D <NA> D
5 5 E E C C <NA> E
6 6 C E <NA> <NA> <NA> C
我认为这可以满足您的需求。对于每一行,它会创建每个字母的 table 频率并选择最大的,同时保留并列的列顺序。然后 returns 这个 table.
中第一列的名称感谢 Henrik 提出的改进建议。
df$New.Group <- apply(df[-1], 1, function(x) {
names(which.max(table(factor(x, unique(x)))))
})
df
#> ID Group1 Group2 Group3 Group4 Group5 New.Group
#> 1 1 A E A <NA> A A
#> 2 2 <NA> C A C D C
#> 3 3 C C <NA> <NA> <NA> C
#> 4 4 <NA> <NA> <NA> D <NA> D
#> 5 5 E E C C <NA> E
#> 6 6 C E <NA> <NA> <NA> C
使用 dplyr
和 vctrs
的一个选项(利用 vec_count()
中的 location
参数,“按第一次看到键的位置排序”)可以是:
df %>%
rowwise() %>%
mutate(New.Group = na.omit(vec_count(c_across(starts_with("Group")), "location")) %>%
slice_max(count, with_ties = FALSE) %>%
pull(key))
ID Group1 Group2 Group3 Group4 Group5 New.Group
<int> <fct> <fct> <fct> <fct> <fct> <fct>
1 1 A E A <NA> A A
2 2 <NA> C A C D C
3 3 C C <NA> <NA> <NA> C
4 4 <NA> <NA> <NA> D <NA> D
5 5 E E C C <NA> E
6 6 C E <NA> <NA> <NA> C
或者:
df %>%
rowwise() %>%
mutate(New.Group = names(which.max(with(na.omit(vec_count(c_across(starts_with("Group")), "location")), setNames(count, key)))))
我们可以使用Mode
函数
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
df$New.Group <- apply(df[-1], 1, FUN = function(x) Mode(na.omit(x)))
df$New.Group
#[1] "A" "C" "C" "D" "E" "C"