本文首先发布于简书[1],本人在对相关知识有进一步理解后对本文进行修改,以便于中文更好地理解。来源:vignettes/programming.Rmd[2]
大多数 dplyr 函数使用非标准计算(NSE)。这是一个术语——意味着它们不遵循通常的计算规则。相反,它们捕获你键入的表达式并以自定义的方式对其进行计算。这让 dplyr 代码有两个主要优点:
- 数据框的操作可以简洁地表达,因为你不需要重复输入数据框名称。例如你可以这样写filter(df, x == 1, y == 2, z == 3)来代替df[dfx == 1 & df
- dplyr 可以选择以不同的方式计算结果与base R 相结合。
不幸的是,这些好处不是免费的。有两个主要缺点:
- 大多数dplyr参数不是透明。这意味着你不能用一个看似等价的对象代替一个在别处定义的值。换句话说,这个代码:
df <- tibble(x = 1:3, y = 3:1)
filter(df, x == 1)
## # A tibble: 1 x 2
## x y
## <int> <int>
## 1 1 3
不等价下面这个代码:
代码语言:javascript复制my_var <- x
filter(df, my_var == 1)
# Error: object 'x' not found
或是这个代码:
代码语言:javascript复制 my_var <- "x"
filter(df, my_var == 1)
## # A tibble: 0 x 2
## # ... with 2 variables: x <int>, y <int>
这使得很难改变被 dplyr 动词计算的参数来创建函数(这一点很重要,如果你使用 dplyr 进行数据框操作,会发现很好用,但是如果你用它创建函数,你会发现它总是以一种无法被理解的形式报错)。
- dplyr代码不明确,取决于在哪里定义了哪些变量, filter(df, x == y)可以等价于下面任意一个:df[dfx == dfy, ]df[dfx == y, ]df[x == dfy, ]df[x == y, ]
这在交互式工作时非常有用(因为它可以节省打字时间和减少打字量,快速发现问题),但使创建函数比你想要的更不可预测。
幸运的是,dplyr 提供了克服这些挑战的工具。他们需要多一点打字,但少量的前期工作是值得的,因为他们从长远来看可以帮助你节省时间。
这篇文章有两个目标:
- 演示如何使用dplyr的pronouns和quasiquotation编写可靠的函数,以减少数据分析代码中的重复。
- 教你基本理论,包括quosures——一个存储表达式和环境的数据结构,以及tidyeval——底层工具包。