1. sci666首页
  2. 实用技巧
  3. 生物信息学

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

这些可能会帮助到你: 问答社区 | 共享百度SVIP | 留言建议

欢迎入群交流:生信分析群: 732179952 · Meta分析群: 797345521 · 医学科研交流群: 797345521

发表评论

电子邮件地址不会被公开。 必填项已用*标注