【问题标题】:R - group by 2 variables and set highest value as new column?R - 按2个变量分组并将最高值设置为新列?
【发布时间】:2020-06-30 17:47:08
【问题描述】:

我有以下数据

df <- data.frame("group1" = c("A","B","B","C","D","D","C","E","E","A","B","B","C","D","D","C","E","E"),
                 "group2" = c("X","Y","Z","Z","W","F","Z","N","M","D","F","U","T","R","R","S","S","O"),
                 "val" = c(232,200,3321,400,600,500,22,33,1200,555,200,888,43,600,500,800,900,3213))

我想添加两个新列:

  • 第 1 列将显示每个 group1 值具有最高“val”的 group2 值
  • 第 2 列会做同样的事情,但会显示最大值占总数的百分比

所以,首先对数据进行分组:

df %>% group_by(group1,group2) %>% summarise("totalval" = sum(val)) %>% arrange(group1, desc(totalval))
# A tibble: 16 x 3
# Groups:   group1 [5]
   group1 group2 totalval
   <fct>  <fct>     <dbl>
 1 A      D           555
 2 A      X           232
 3 B      Z          3321
 4 B      U           888
 5 B      F           200
 6 B      Y           200
 7 C      S           800
 8 C      Z           422
 9 C      T            43
10 D      R          1100
11 D      W           600
12 D      F           500
13 E      O          3213
14 E      M          1200
15 E      S           900
16 E      N            33

所以我希望第 1 列具有值“D”,因为 group2 列中的值“D”在所有第 1 组中具有最高值。第 2 列将显示值 555 / (555 + 232) = 0.70对于 group1 列中值为“A”的所有行。

我找到了一种方法来获取第 1 列,方法是创建一个具有最高值的临时表,然后将其连接回主表,但我认为它相当复杂 - 我相信有一种更简洁的方法。我也不确定如何获得要添加的百分比(如上所述的第 2 列)。

到目前为止我的解决方案:

#add in overall val to use for percentages
df <- df %>% group_by(group1) %>% mutate("g1_total_val" = sum(val)) %>% ungroup()

#create temp table with selected values
t2 <- df %>% group_by(group1,group2) %>% summarise("totalval" = sum(val)) %>% arrange(group1, desc(totalval)) %>% 
        slice(1:1) %>% mutate("highest_g2" = group2) %>% select(group1, highest_g2)

df <- df %>% left_join(t2,on = "group1")

任何有关如何获取第 2 列以及添加到第 1 列的更简单方法的帮助都会很棒。

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以使用which.max获取第一列最大值的索引,然后将max除以第二列的sum如下:

    library(tidyverse)
    
    df %>%
      group_by(group1, group2) %>%
      summarise(totalval = sum(val)) %>%
      arrange(group1, desc(totalval)) %>% 
      mutate(col1 = group2[which.max(totalval)],
             col2 = max(totalval) / sum(totalval))
    

    这给出了:

       group1 group2 totalval col1   col2
       <fct>  <fct>     <dbl> <fct> <dbl>
     1 A      D           555 D     0.705
     2 A      X           232 D     0.705
     3 B      Z          3321 Z     0.721
     4 B      U           888 Z     0.721
     5 B      F           200 Z     0.721
     6 B      Y           200 Z     0.721
     7 C      S           800 S     0.632
     8 C      Z           422 S     0.632
     9 C      T            43 S     0.632
    10 D      R          1100 R     0.5  
    11 D      W           600 R     0.5  
    12 D      F           500 R     0.5  
    13 E      O          3213 O     0.601
    14 E      M          1200 O     0.601
    15 E      S           900 O     0.601
    16 E      N            33 O     0.601
    

    编辑 如果你想保持原来的行数,你应该把summarise替换成mutate,这样:

    df %>%
      group_by(group1, group2) %>%
      mutate(totalval = sum(val)) %>%
      group_by(group1) %>% 
      arrange(group1, desc(totalval)) %>% 
      mutate(col1 = group2[which.max(totalval)],
             col2 = max(totalval) / sum(totalval))
    

    请注意,summarise 会自动“剥离”第二个分组变量,但 mutate 不会,所以我手动重新进行分组。
    这给出了添加了 2 列的原始 18 行。

    【讨论】:

    • 感谢您的回答。我的实际数据有更多列,因此汇总会弄乱数据(对不起,我应该提到它)。有没有没有总结的方法?
    • summarise 是您提供的代码的复制粘贴;我只是添加了mutate。总结有什么问题?分享您的输入数据和预期输出,以便我更好地帮助您。
    • 原始数据集有 18 行,上面的汇总有 16 行 - 我希望最终结果返回给我原始数据集,但基本上是新的两列。对不起,我应该说清楚
    • 我对我的答案进行了编辑。这样做是你想要的吗?
    • 谢谢!是的,它几乎是这样,第 1 列是完全正确的,但是 col2 公式应该是 max(totalval) / sum(val) 而不是 sum (totalval) 在分母中。不过很容易修复 - 再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2019-08-07
    • 2018-11-25
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 2018-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多