【问题标题】:Get the most frequent value per row and account for ties [duplicate]获取每行最频繁的值并考虑关系[重复]
【发布时间】:2020-11-11 03:50:37
【问题描述】:

样本数据:

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

【问题讨论】:

  • 列优先级究竟是如何定义的?
  • 第一列比第二列重要,第二列比第三列重要,以此类推。
  • 相关,但似乎没有处理“如果有关系,请选择第一个值”:Find the most frequent value by row
  • @Henrik 对于我们的一个内部包,我制作了rowMode-function,您可以在其中设置函数应该如何处理关联和缺失值。 Posted it here.
  • 感谢@Jaap 的提醒。不错!

标签: r count recode


【解决方案1】:

我认为这可以满足您的需求。对于每一行,它创建一个每个字母的频率表并选择最大的,同时保留列顺序。然后它返回此表中第一列的名称。

感谢 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

【讨论】:

  • @Henrik 是的,这样更好。我以为我已经尝试过并出于某种原因拒绝了它,但我认为它在逻辑上是相同的(并且更整洁)。谢谢。
  • 它确实考虑了关系
【解决方案2】:

使用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)))))

【讨论】:

    【解决方案3】:

    我们可以使用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"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      • 2017-01-06
      • 2018-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多