r - 什么!!R中的运算符均值
问题描述
任何人都可以解释一下,我们需要什么!!
,!!!
或者{{}}
运营商来自rlang
哪里?我试图了解更多关于 quasiquotation 但没有得到任何东西。
我已经在 Stack 上看到了几篇关于 curly-curly 运算符的帖子,并且了解到{{
我们在将数据帧的变量(或我们对象的其他子对象)传递给函数时使用。但是在阅读了quote/unquote之后,我对所有这些运算符及其用法完全感到困惑。
为什么我们需要它,为什么有些函数没有它就不能读取参数,最后,它们实际上是如何工作的?
如果您以我能理解的最简单的方式给出答案,我将不胜感激(也许有例子?)。
解决方案
!!
and运算符是占位符,用于将{{
变量标记为已被引用。它们通常仅在您打算使用tidyverse
. 喜欢利用 NSE (tidyverse
非标准评估)来减少重复量。最常见的应用是针对"data.frame"
类,其中表达式/符号在搜索其他范围之前在 data.frame 的上下文中进行评估。为了让它工作,一些特殊的函数(比如在 package 中dplyr
)有被引用的参数。引用表达式,就是保存构成表达式的符号并防止计算(在tidyverse
他们使用“quosures”,这就像一个带引号的表达式,除了它包含对表达式所产生环境的引用)。虽然 NSE 非常适合交互式使用,但它的编程难度明显更高。让我们考虑dplyr::select
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
iris <- as_tibble(iris)
my_select <- function(.data, col) {
select(.data, col)
}
select(iris, Species)
#> # A tibble: 150 × 1
#> Species
#> <fct>
#> 1 setosa
#> 2 setosa
#> 3 setosa
#> 4 setosa
#> 5 setosa
#> 6 setosa
#> 7 setosa
#> 8 setosa
#> 9 setosa
#> 10 setosa
#> # … with 140 more rows
my_select(iris, Species)
#> Error: object 'Species' not found
我们遇到错误,因为在参数范围内my_select
使用col
标准评估进行评估并且找不到名为 的变量Species
。
如果我们尝试在全局环境中创建一个变量,我们会看到该函数有效 - 但它不符合tidyverse
. 事实上,他们会制作一个注释来通知您这是模棱两可的使用。
Species <- "Sepal.Width"
my_select(iris, Species)
#> Note: Using an external vector in selections is ambiguous.
#> ℹ Use `all_of(col)` instead of `col` to silence this message.
#> ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
#> This message is displayed once per session.
#> # A tibble: 150 × 1
#> Sepal.Width
#> <dbl>
#> 1 3.5
#> 2 3
#> 3 3.2
#> 4 3.1
#> 5 3.6
#> 6 3.9
#> 7 3.4
#> 8 3.4
#> 9 2.9
#> 10 3.1
#> # … with 140 more rows
为了解决这个问题,我们需要防止评估enquo()
和取消!!
引用或仅使用{{
.
my_select2 <- function(.data, col) {
col_quo <- enquo(col)
select(.data, !!col_quo) #attempting to find whatever symbols were passed to `col` arugment
}
#' `{{` enables the user to skip using the `enquo()` step.
my_select3 <- function(.data, col) {
select(.data, {{col}})
}
my_select2(iris, Species)
#> # A tibble: 150 × 1
#> Species
#> <fct>
#> 1 setosa
#> 2 setosa
#> 3 setosa
#> 4 setosa
#> 5 setosa
#> 6 setosa
#> 7 setosa
#> 8 setosa
#> 9 setosa
#> 10 setosa
#> # … with 140 more rows
my_select3(iris, Species)
#> # A tibble: 150 × 1
#> Species
#> <fct>
#> 1 setosa
#> 2 setosa
#> 3 setosa
#> 4 setosa
#> 5 setosa
#> 6 setosa
#> 7 setosa
#> 8 setosa
#> 9 setosa
#> 10 setosa
#> # … with 140 more rows
总之,您真的只需要!!
并且{{
如果您尝试以编程方式应用 NSE 或对该语言进行某种类型的编程。
!!!
用于将某种列表/向量拼接到某个引用表达式的参数中。
library(rlang)
quo_let <- quo(paste(!!!LETTERS))
quo_let
#> <quosure>
#> expr: ^paste("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
#> "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
#> "Z")
#> env: global
eval_tidy(quo_let)
#> [1] "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
由reprex 包于 2021-08-30 创建(v2.0.1)
推荐阅读
- ios - 为什么这段代码会重新渲染 SwiftUI 视图的主体?
- javascript - AngularJs 副本:不放在表格的第二行
- pyspark - Spark优化编码
- javascript - 我有这两个吨位计算器。第一个工作得很好。我该如何修复第二个?我的 Javascript 有问题吗?
- angular - APP_INITIALIZER 不返回
- java - 如何创建相同对象的副本(例如标签)?
- filter - 使用 ffmpeg 将所有帧聚合为一张图像
- dart - 在 Dart 中使用 PointyCastle 进行 SHA-384/PSS 签名验证
- node.js - 当我尝试从 firebase 导出 db 时编译节点模块失败
- r - 用前一行的值替换 NA 或用 R 中的向量循环进行变异