tidyverse evaluation

2020-09-15 15:42:50 浏览数 (2)

tidy evaluation

sunqi
2020/8/5

概述

也称作非标准评估

代码

代码语言:javascript复制
rm(list = ls())
library("tidyverse")
library(rlang)
# 在编写代码时遇到不同数据集或者不同变量的操作比如
iris %>%
  group_by(Species) %>%
  summarise(mean=mean(Sepal.Length))
代码语言:javascript复制
## # A tibble: 3 x 2
##   Species     mean
##   <fct>      <dbl>
## 1 setosa      5.01
## 2 versicolor  5.94
## 3 virginica   6.59
代码语言:javascript复制
# 如果换个变量,那么就需要重新编写代码
# 于是乎,想到了用自定义函数进行重复性的操作
# 但是R语言函数的传递和python是不一样的
# 因此,在tidyverse中,对这种情况进行了解决

# !!对表达式求解
# quo 生成表达式
group_mean <- function(data, var_group,varname, var_mean) {
  data %>%
    # 对变量进行!!
  group_by(!!var_group) %>%
  summarise(!!varname:=mean(!!var_mean))
}
# 调用的时候使用quo函数
group_mean(data=iris,
           var_group=quo(Species),
           varname="mean_sepal.length",
           var_mean=quo(Sepal.Length))
代码语言:javascript复制
## # A tibble: 3 x 2
##   Species    mean_sepal.length
##   <fct>                  <dbl>
## 1 setosa                  5.01
## 2 versicolor              5.94
## 3 virginica               6.59
代码语言:javascript复制
# 上述函数实现了对字符和函数名的调用
# 但是输入的时候需要书写quo
# 这个时候可以使用enquo
group_mean <- function(data, var_group,varname, var_mean) {
  var_group <- enquo(var_group)
  var_mean <- enquo(var_mean)
  data %>%
  group_by(!!var_group) %>%
  summarise(!!varname:=mean(!!var_mean))
}
group_mean(data=iris,
           var_group=Species,
           varname="mean_sepal.length",
           var_mean=Sepal.Length)
代码语言:javascript复制
## # A tibble: 3 x 2
##   Species    mean_sepal.length
##   <fct>                  <dbl>
## 1 setosa                  5.01
## 2 versicolor              5.94
## 3 virginica               6.59
代码语言:javascript复制
## 上述代码的两次引用还是不太方便
## 使用大括号
## 大括号同时包含的转换表达式和求解表达式
group_mean <- function(data, var_group,varname, var_mean) {
  data %>%
  group_by({{var_group}}) %>%
  summarise({{varname}}:= mean ({{var_mean}}))
}
group_mean(data=iris,
           var_group=Species,
           varname="mean_sepal.length",
           var_mean=Sepal.Length)
代码语言:javascript复制
## # A tibble: 3 x 2
##   Species    mean_sepal.length
##   <fct>                  <dbl>
## 1 setosa                  5.01
## 2 versicolor              5.94
## 3 virginica               6.59
代码语言:javascript复制
# 现版本的tidyverse还可以这样写函数
# across函数支持对队列执行相同的操作
sum_group_vars <- function(data,
                           group_vars,
                           sum_vars){
  data %>%
    group_by(across({{ group_vars }})) %>%
    summarise(n = n(),
              across({{ sum_vars }},
                     list(mean = mean, sd = sd))
              )
}
# 调用函数
sum_group_vars(mpg, c(model, year), c(hwy, cty)) %>% head()
代码语言:javascript复制
## # A tibble: 6 x 7
## # Groups:   model [3]
##   model        year     n hwy_mean hwy_sd cty_mean cty_sd
##   <chr>       <int> <int>    <dbl>  <dbl>    <dbl>  <dbl>
## 1 4runner 4wd  1999     4     19     1.41     15.2   0.5
## 2 4runner 4wd  2008     2     18.5   2.12     15     1.41
## 3 a4           1999     4     27.5   1.73     18.2   2.06
## 4 a4           2008     3     29.3   2.08     19.7   1.53
## 5 a4 quattro   1999     4     25.2   0.5      16.5   1.29
## 6 a4 quattro   2008     4     26.2   1.5      17.8   2.22
代码语言:javascript复制
# 处理多个参数
# 使用... 代替传递参数



grouped_mean <- function(df, summary_var, ...) {
  summary_var <- enquo(summary_var)
    group_var <- enquos(...)
 
  df %>%
    group_by(!!!group_var) %>%
    summarise(mean = mean(!!summary_var))
}
# 运行函数
# 这里传递两个分组变量
grouped_mean(mtcars, disp, cyl, am)
代码语言:javascript复制
## # A tibble: 6 x 3
## # Groups:   cyl [3]
##     cyl    am  mean
##   <dbl> <dbl> <dbl>
## 1     4     0 136.
## 2     4     1  93.6
## 3     6     0 205.
## 4     6     1 155
## 5     8     0 358.
## 6     8     1 326
代码语言:javascript复制
## 试试ggplot
## 编写一个绘制iris箱式图的函数

box <- function(data, var_group, var_target) {
  data %>% ggplot(aes(x={{var_group}},y={{var_target}})) 
    geom_boxplot()
}
box(data = iris,var_group = Species,var_target = Sepal.Length)

结束语

这么久以来,这是我最喜欢的一个R脚本,解决了我一直以来函数编写的问题,以前都是使用eval(parse(text=“代码字符串”))来实现自定义函数的传递功能,另外R for data science,这本书贵不贵?,想买一本看看。

love&peace

0 人点赞