【问题标题】:Sum sub groups with dplyr使用 dplyr 对子组求和
【发布时间】:2020-07-14 09:11:54
【问题描述】:

我正在尝试使用 mutate 将子组与 dplyr 相加,但这意味着我需要知道每个行组才能创建条件。这个想法是不改变当前的分组,如下面的代码所示:

mutate(mtcars, cond_disp = ifelse(vs==1,sum(disp[vs==1]),sum(disp[vs==0])))

是否有动态的方法来实现这一点?

【问题讨论】:

  • 您可以来回更改分组
  • 如果你想对值求和,我认为你想要summarise 而不是mutate。如果您想根据子集进行操作,请先 group_by。试试mtcars %>% group_by(vs) %>% summarise(cond_disp = sum(disp))

标签: r dplyr


【解决方案1】:

您可以使用group_by(vs)summarise 来实现。但这里希望的是带有mutate 的版本。

library(tidyverse)

mtcars %>% 
  group_by(vs) %>% 
  #summarise(cond_disp = sum(disp))
  mutate(cond_disp = sum(disp))
#> # A tibble: 32 x 12
#> # Groups:   vs [2]
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb cond_disp
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>     <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4     5529.
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4     5529.
#>  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1     1854.
#>  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1     1854.
#>  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2     5529.
#>  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1     1854.
#>  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4     5529.
#>  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2     1854.
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2     1854.
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4     1854.
#> # … with 22 more rows

【讨论】:

    【解决方案2】:

    dplyr::mutate() 将多行作为方程右侧函数的输入,这些函数是 mutate() 的参数。如 cmets 中所述,可以使用 group_by() 将右侧函数的输入分解为子组。这消除了mutate() 中对原始问题中指定的条件逻辑的需求。

    我们将通过计算原始帖子中的cond_disp 来说明,并包含n 以计算摘要数据中包含的行数。

    mtcars %>% group_by(vs) %>% 
         mutate(cond_disp = sum(disp),
                n = n()) -> result
    result[,c("vs","n","cond_disp","disp")]
    
    
    # A tibble: 32 x 4
    # Groups:   vs [2]
          vs     n cond_disp  disp
       <dbl> <int>     <dbl> <dbl>
     1     0    18     5529.  160 
     2     0    18     5529.  160 
     3     1    14     1854.  108 
     4     1    14     1854.  258 
     5     0    18     5529.  360 
     6     1    14     1854.  225 
     7     0    18     5529.  360 
     8     1    14     1854.  147.
     9     1    14     1854.  141.
    10     1    14     1854.  168.
    # … with 22 more rows
    

    mutate() 方法在需要逐行计算百分比值时非常有用,其中百分比的分母是按组组合内的列的总和。为了说明这一点,我们将计算 V 型发动机与直列发动机的总排量百分比,打印结果,并打印pct_disp 的总和,以说明 V 型发动机等于 100。

    mtcars %>% group_by(vs) %>% 
         mutate(pct_disp = 100* disp / sum(disp),
                n = n()) -> result
    result[result$vs==0,c("vs","n","disp","pct_disp")]
    sum(result$pct_disp[result$vs==0])
    
    
    # A tibble: 18 x 4
    # Groups:   vs [1]
          vs     n  disp pct_disp
       <dbl> <int> <dbl>    <dbl>
     1     0    18  160      2.89
     2     0    18  160      2.89
     3     0    18  360      6.51
     4     0    18  360      6.51
     5     0    18  276.     4.99
     6     0    18  276.     4.99
     7     0    18  276.     4.99
     8     0    18  472      8.54
     9     0    18  460      8.32
    10     0    18  440      7.96
    11     0    18  318      5.75
    12     0    18  304      5.50
    13     0    18  350      6.33
    14     0    18  400      7.23
    15     0    18  120.     2.18
    16     0    18  351      6.35
    17     0    18  145      2.62
    18     0    18  301      5.44
    > sum(result$pct_disp[result$vs==0])
    [1] 100
    

    何时使用 summarise()

    dplyr::summarise() 如果想要汇总数据而不向管道中的输入数据框添加额外的列,则很有用。 summarise() 的结果是管道中 group_by() 规范中的每个变量组合的一行,汇总数据的列。

    mtcars %>% group_by(vs) %>% 
         summarise(cond_disp = sum(disp),
                n = n()) 
    # A tibble: 2 x 3
         vs cond_disp     n
      <dbl>     <dbl> <int>
    1     0     5529.    18
    2     1     1854.    14
    

    逐行计算

    如果需要使用 R 函数计算行内各列的值,可以使用 rowwise() 函数来防止 mutate()mutate() 内方程右侧的函数中使用多行.

    为了说明,我们将对vsam 的值求和。请注意,输出中n = n() 的结果对于打印的每一行都是 1。

    mtcars %>% rowwise(.) %>% 
         mutate(cond_binary = sum(vs,am),
                n = n()) -> result
    result[,c("vs","am","n","cond_binary")]
    
    
    # A tibble: 32 x 4
    # Rowwise: 
          vs    am     n cond_binary
       <dbl> <dbl> <int>       <dbl>
     1     0     1     1           1
     2     0     1     1           1
     3     1     1     1           2
     4     1     0     1           1
     5     0     0     1           0
     6     1     0     1           1
     7     0     0     1           0
     8     1     0     1           1
     9     1     0     1           1
    10     1     0     1           1
    # … with 22 more rows
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-29
      • 2020-04-04
      • 2018-04-05
      • 2016-08-02
      • 1970-01-01
      • 2015-05-06
      • 2022-06-29
      相关资源
      最近更新 更多