" summarise_at"和" mutate_if"用于字符变量的描述性统计

时间:2017-11-28 18:27:45

标签: r dplyr

我想在同一时间对多个字符变量使用summarise_atmutate_at。我已经看过许多使用整数变量的例子,但我不能弄清楚字符变量。下面是我用来为字符(或因子)变量生成描述性统计信息的代码。

library(tidyverse)

# First block of code
starwars %>%
  group_by(gender) %>%
  summarise (n = n()) %>%
  mutate(totalN = (cumsum(n))) %>%
  mutate(percent = round((n / sum(n)), 3)) %>%
  mutate(cumpercent = round(cumsum(freq = n / sum(n)),3))

这会产生:

A tibble: 5 x 5
         gender     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1        female    19     19   0.218      0.218
2 hermaphrodite     1     20   0.011      0.230
3          male    62     82   0.713      0.943
4          none     2     84   0.023      0.966
5          <NA>     3     87   0.034      1.000

我想生成同样的东西,但是对于多个字符(或因子)变量一次。在这种情况下,让我们使用变量gendereye_color这就是我的尝试:

starwars %>%        
      summarise_at(vars(gender, eyecolor) (n = n()) %>%
      mutate_at(vars(gender, eyecolor) (totalN = (cumsum(n))) %>%
      mutate_at(vars(gender", "eyecolor) (percent = round((n / sum(n)), 3)) %>%
      mutate_at(vars(gender, eyecolor) (cumpercent = round(cumsum(freq = n / sum(n)),3))))))

我收到以下错误:

Error in eval(expr, envir, enclos) : attempt to apply non-function

我了解有使用funs调用的内置函数,但我不想使用它们。我尝试过以不同的方式使用代码来使其工作,但是已经很短了。

我想要制作的是这样的:

A tibble: 5 x 5
         gender     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1        female    19     19   0.218      0.218
2 hermaphrodite     1     20   0.011      0.230
3          male    62     82   0.713      0.943
4          none     2     84   0.023      0.966
5          <NA>     3     87   0.034      1.000

A tibble: 15 x 5
      eye_color     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1         black    10     10   0.115      0.115
2          blue    19     29   0.218      0.333
3     blue-gray     1     30   0.011      0.345
4         brown    21     51   0.241      0.586
5          dark     1     52   0.011      0.598
6          gold     1     53   0.011      0.609
7 green, yellow     1     54   0.011      0.621
8         hazel     3     57   0.034      0.655
9        orange     8     65   0.092      0.747
10         pink     1     66   0.011      0.759
11          red     5     71   0.057      0.816
12     red, blue    1     72   0.011      0.828
13       unknown    3     75   0.034      0.862
14         white    1     76   0.011      0.874
15        yellow    11     87   0.126     1.000

也许循环会更好?现在我有很多行代码来为每个字符变量生成描述性统计信息,因为我必须为每个变量运行第一个代码块(如上所述)。如果我能列出我想要使用的变量并在第一个代码块中运行它们,那就太棒了。

1 个答案:

答案 0 :(得分:3)

根据您的预期输出,mutate_at不是您想要的,因为它会在所选列上发生变化。您要做的是分别group_by gendereye_color。这是将摘要代码编写到函数中的好地方:

library(tidyverse)
library(rlang)

summary_func = function(group_by_var){
  group_by_quo = enquo(group_by_var)
  starwars %>%
    group_by(!!group_by_quo) %>%
    summarise(n = n()) %>%
    mutate(totalN = (cumsum(n)),
           percent = round((n / sum(n)), 3),
           cumpercent = round(cumsum(freq = n / sum(n)),3))
}

<强>结果:

> summary_func(gender)
# A tibble: 5 x 5
         gender     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1        female    19     19   0.218      0.218
2 hermaphrodite     1     20   0.011      0.230
3          male    62     82   0.713      0.943
4          none     2     84   0.023      0.966
5          <NA>     3     87   0.034      1.000

> summary_func(eye_color)
# A tibble: 15 x 5
       eye_color     n totalN percent cumpercent
           <chr> <int>  <int>   <dbl>      <dbl>
 1         black    10     10   0.115      0.115
 2          blue    19     29   0.218      0.333
 3     blue-gray     1     30   0.011      0.345
 4         brown    21     51   0.241      0.586
 5          dark     1     52   0.011      0.598
 6          gold     1     53   0.011      0.609
 7 green, yellow     1     54   0.011      0.621
 8         hazel     3     57   0.034      0.655
 9        orange     8     65   0.092      0.747
10          pink     1     66   0.011      0.759
11           red     5     71   0.057      0.816
12     red, blue     1     72   0.011      0.828
13       unknown     3     75   0.034      0.862
14         white     1     76   0.011      0.874
15        yellow    11     87   0.126      1.000

我们的想法是将您的摘要代码转换为函数,以便您可以在不同的group_by变量上应用相同的代码。来自enquo的{​​{1}}将提供的代码提取到rlang,并将其与调用group_by_var的环境捆绑在一起。然后,您可以使用quosure取消引用!!步骤中的group_by_quo。这样可以进行非标准评估(即键入group_by而不是summary_func(gender)

如果您不想为summary_func("gender")的每个变量拨打summary_func,可以将group_by代码包含在dplyr map中并且取消引用作为purrr参数提供的group_by_quo的每个参数。请注意从...enquo的更改,以将quos的每个参数转换为...的列表:

quosure

您现在可以执行此操作:

summary_func = function(...){
  group_by_quo = quos(...)

  map(group_by_quo, ~{
    starwars %>%
      group_by(!!.x) %>%
      summarise(n = n()) %>%
      mutate(totalN = (cumsum(n)),
             percent = round((n / sum(n)), 3),
             cumpercent = round(cumsum(freq = n / sum(n)),3))
  })
}

或带有summary_func(gender, eye_color) 的字符变量名称向量:

group_by

<强>结果:

group_vars = c("gender", "eye_color")
summary_func(!!!syms(group_vars))