R 语言里的非标准求值

引言


非标准求值 (Non-Standard Evaluation,NSE) 是 R 语言的一个强大且独特的特性,它允许表达式在函数或某个上下文中被捕捉并延迟评估,而不是像通常的标准计算(SE, Standard Evaluation) 那样直接计算。大部分编程语言中,函数在被调用时会立即评估传入的参数,但在 R 中,使用 NSE 可以捕获参数并延迟进行求值。这种特性在 dplyr、ggplot2 等 R 包中广泛应用。
NSE 的应用场景主要有:
捕捉未求值的表达式 并延迟对其求值。
方便基于列名 (比如数据框的列名)进行操作,而无需把列名硬编码成字符串。

有时候我们需要包装 dplyr 或者 ggplot 这种类似的函数的时候,非标准求值 可以很大帮助我们简化代码。下面两个链接可以帮助我们了解,此外 rlang 包也可以好好学习一下里面的函数。
https://adv-r.hadley.nz/evaluation.html
https://dplyr.tidyverse.org/articles/programming.html
示例


这里我们举几个例子,我们自己尝试模仿编写dplyr中的 select,filter 和 mutate 函数。
my_select
library(rlang)
library(dplyr)

my_select <- function(data,…){
cls <- enquos(…)
data[,sapply(cls,as_name)]
}

my_select(mtcars,mpg,cyl) |> head()

mpg cyl

Mazda RX4 21.0 6

Mazda RX4 Wag 21.0 6

Datsun 710 22.8 4

Hornet 4 Drive 21.4 6

Hornet Sportabout 18.7 8

Valiant 18.1 6

my_filter
my_filter <- function(data, …) {
condition <- enquos(…)

for (i in seq_along(condition)) {
ftdata <- data[eval_tidy(condition[[i]], data), ]

}

ftdata
}

my_filter(mtcars,mpg > 30)

mpg cyl disp hp drat wt qsec vs am gear carb

Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1

Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2

Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1

Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2

my_filter(mtcars,mpg > 30 & gear == 4)

mpg cyl disp hp drat wt qsec vs am gear carb

Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1

Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2

Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1

my_mutate
my_mutate <- function(data, …) {
new_columns <- enquos(…)

new_column_names <- names(new_columns)

for (i in seq_along(new_columns)) {
col_name <- new_column_names[i]
data[[col_name]] <- eval_tidy(new_columns[[i]], data)
}

return(data)
}

mtcars |> my_mutate(new = mpg + disp) |> head()

mpg cyl disp hp drat wt qsec vs am gear carb new

Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 181.0

Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 181.0

Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 130.8

Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 279.4

Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 378.7

Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 243.1

结尾


路漫漫其修远兮,吾将上下而求索。
欢迎加入生信交流群。加我微信我也拉你进 微信群聊 老俊俊生信交流群 (微信交流群需收取 20 元入群费用,一旦交费,拒不退还!(防止骗子和便于管理)) 。

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/422933.html

联系我们
联系我们
分享本页
返回顶部