R tips:dplyr编程

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

生物信息学

pandas中的数据处理利器-groupby

2020-6-30 21:36:46

生物信息学

基因注释流程MAKER的配置文件详解

2020-7-1 17:14:23

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索