dplyr的函数由于使用tidy evaluation(R中的一种非标准执行(NSE)实现方式)的方法,可以使得其具有更好的易用性:变量不需要绝对引用和引号包裹。
根据使用的NSE的类别不同,dplyr的函数可以分为两类:
- data masking:
arrange()
,count()
,filter()
,group_by()
,mutate()
,summarise()
,data masking可以使得使用用户数据变量像使用环境变量一样易用。 - tidy selection:
across()
,relocate()
,rename()
,select()
,pull()
,使得可以很方便的根据位置、名称、类别去选择数据变量。
环境变量与数据变量
环境变量是存在于环境中的变量,一般通过”<-“来创建。
数据变量是一种存在于数据框(data.frame)的变量,常常是来源于数据文件。比如mtcars中mpg、cyl等等。
根据所用的NSE的类别,需要区别对待dplyr函数的编程。
Data masking
如果想要操作的数据变量名称来源于环境变量,那么使用特殊的指代词.data来完成。
library(tidyverse)
# 常规使用是会报错的
grp_var <- "vs"
mtcars %>% group_by(grp_var) %>% summarise(mean_disp = mean(disp))
#Error: Column `grp_var` is unknown
# 使用.data即可
mtcars %>% group_by(.data[[grp_var]]) %>% summarise(mean_disp = mean(disp))
# A tibble: 2 x 2
# vs mean_disp
# <dbl> <dbl>
#1 0 307.
#2 1 132.
如果想要操作的数据变量来源于函数参数(指的一个环境变量上存在一个promise),那么使用{{}}包裹。
一个函数在调用时,其参数存在一个promise。原因在于R的参数是 lazily evaluated,也就是说直到使用此参数前,这些参数并没有实际值(实际值也就是实参),而只有一个获取其实际值的方法(promise)。
# 使用{{}}包裹
summarise_grp <- function(data, grp){
data %>% group_by({{grp}}) %>% summarise(mean_disp = mean(disp))
}
mtcars %>% summarise_grp(vs)
# # A tibble: 2 x 2
# vs mean_disp
# <dbl> <dbl>
# 1 0 307.
# 2 1 132.
Tidy selection
如果想要操作的数据变量名称来源于环境变量,那么使用all_of或者any_of。
grp_var <- c("vs","cyl")
mtcars %>% select(all_of(grp_var)) %>% head
# vs cyl
# Mazda RX4 0 6
# Mazda RX4 Wag 0 6
# Datsun 710 1 4
# Hornet 4 Drive 1 6
# Hornet Sportabout 0 8
# Valiant 1 6
mtcars %>% select(!all_of(grp_var)) %>% head
# mpg disp hp drat wt qsec am gear carb
# Mazda RX4 21.0 160 110 3.90 2.620 16.46 1 4 4
# Mazda RX4 Wag 21.0 160 110 3.90 2.875 17.02 1 4 4
# Datsun 710 22.8 108 93 3.85 2.320 18.61 1 4 1
# Hornet 4 Drive 21.4 258 110 3.08 3.215 19.44 0 3 1
# Hornet Sportabout 18.7 360 175 3.15 3.440 17.02 0 3 2
# Valiant 18.1 225 105 2.76 3.460 20.22 0 3 1
all_of和any_of的区别在于,如果不是所有的变量都存在于数据框中,那么all_of会报错,any_of不会报错,按需使用。
如果想要操作的数据变量来源于函数参数,那么使用{{}}包裹。
map(grp_var, function(x){
mtcars %>% select({{x}}) %>% head
})
# [[1]]
# vs
# Mazda RX4 0
# Mazda RX4 Wag 0
# Datsun 710 1
# Hornet 4 Drive 1
# Hornet Sportabout 0
# Valiant 1
#
# [[2]]
# cyl
# Mazda RX4 6
# Mazda RX4 Wag 6
# Datsun 710 4
# Hornet 4 Drive 6
# Hornet Sportabout 8
# Valiant 6
参考资料
Programming with dplyr :https://dplyr.tidyverse.org/articles/programming.html