获取每行最频繁的值并考虑关系

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,因为它是该行中出现频率最高的值,忽略 NAs。

第 2 行取值 C,因为它也是出现频率最高的值。

第 3 行与第 2 行相同。

第 4 行取值 D,因为它是该行中唯一的值。

在第 5 行中,EC 都有计数 2,但选择了 E,因为它在行中的 C 之前遇到。

第6行,与第5行类似,CE的计数都是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

使用 dplyrvctrs 的一个选项(利用 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"