Quasiquotation 和 ifelse:取消引用未按预期解析
Quasiquotation and ifelse : Unquoting not resolving as expected
我期待我可以使用 rlang
包中的准引用机制,例如 !!
和 quo_name()
来在 mutate()
和 [=15] 中取消引用程序名称=] 功能。但是,它没有像我预期的那样工作,如下所示。它没有解析 mutate()
调用中 ifelse()
数据帧范围内的名称值,而是仅解析参数的字符值。我能够使用基本函数 get()
来做我想做的事。但是,我一定是混淆了什么,并且正在寻找如何在 rlang/quasiquotation 世界中做到这一点。解释和帮助表示赞赏。
suppressPackageStartupMessages(library(tidyverse))
df <- tibble(x=c(1, NA_integer_, 3), y=101:103)
print(df)
#> # A tibble: 3 x 2
#> x y
#> <dbl> <int>
#> 1 1 101
#> 2 NA 102
#> 3 3 103
# Expected behavior
df %>%
mutate(z = ifelse(is.na(x), y, x))
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <dbl>
#> 1 1 101 1
#> 2 NA 102 102
#> 3 3 103 3
# Similar question seemed to be posted here:
# From: https://community.rstudio.com/t/trouble-with-creating-column-names-from-a-passed-argument-in-function/7819/3
# I expect same output as above, but instead, the column `x` gets filled with the name of the column, not appropriate value.
v_colname <- "x"
df %>%
mutate(z := ifelse(is.na(!!v_colname), y, !!v_colname)) %>%
print()
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <chr>
#> 1 1 101 x
#> 2 NA 102 x
#> 3 3 103 x
# Tried variant with `quo_name()`, same unexpected result:
df %>%
mutate(z := ifelse(is.na(!!quo_name(v_colname)), y, !!quo_name(v_colname)))
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <chr>
#> 1 1 101 x
#> 2 NA 102 x
#> 3 3 103 x
# This works, but I assume I am missing something with quasiquotation semantics:
df %>%
mutate(z := ifelse(is.na(get(v_colname)), y, get(v_colname)))
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <dbl>
#> 1 1 101 1
#> 2 NA 102 102
#> 3 3 103 3
# Session info
sessionInfo()
#> R version 3.5.2 (2018-12-20)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 16299)
#>
#> Matrix products: default
#>
#> locale:
#> [1] LC_COLLATE=English_United States.1252
#> [2] LC_CTYPE=English_United States.1252
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C
#> [5] LC_TIME=English_United States.1252
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] bindrcpp_0.2.2 forcats_0.3.0 stringr_1.3.1 dplyr_0.7.8
#> [5] purrr_0.2.5 readr_1.3.1 tidyr_0.8.2 tibble_2.0.1
#> [9] ggplot2_3.1.0 tidyverse_1.2.1
#>
#> loaded via a namespace (and not attached):
#> [1] Rcpp_1.0.0 cellranger_1.1.0 plyr_1.8.4 pillar_1.3.1
#> [5] compiler_3.5.2 highr_0.7 bindr_0.1.1 tools_3.5.2
#> [9] digest_0.6.18 lubridate_1.7.4 jsonlite_1.6 evaluate_0.12
#> [13] nlme_3.1-137 gtable_0.2.0 lattice_0.20-38 pkgconfig_2.0.2
#> [17] rlang_0.3.1 cli_1.0.1 yaml_2.2.0 haven_2.0.0
#> [21] xfun_0.4 withr_2.1.2 xml2_1.2.0 httr_1.4.0
#> [25] knitr_1.21 hms_0.4.2 generics_0.0.2 grid_3.5.2
#> [29] tidyselect_0.2.5 glue_1.3.0 R6_2.3.0 fansi_0.4.0
#> [33] readxl_1.2.0 rmarkdown_1.11 modelr_0.1.2 magrittr_1.5
#> [37] backports_1.1.3 scales_1.0.0 htmltools_0.3.6 rvest_0.3.2
#> [41] assertthat_0.2.0 colorspace_1.4-0 utf8_1.1.4 stringi_1.2.4
#> [45] lazyeval_0.2.1 munsell_0.5.0 broom_0.5.1 crayon_1.3.4
由 reprex package (v0.2.1)
于 2019-02-27 创建
我们可以转换为符号 (sym
) 然后计算 (!!
)
library(dplyr)
df %>%
mutate(z := ifelse(is.na(!!rlang::sym(v_colname)), y, !! rlang::sym(v_colname)))
# A tibble: 3 x 3
# x y z
# <dbl> <int> <dbl>
#1 1 101 1
#2 NA 102 102
#3 3 103 3
我期待我可以使用 rlang
包中的准引用机制,例如 !!
和 quo_name()
来在 mutate()
和 [=15] 中取消引用程序名称=] 功能。但是,它没有像我预期的那样工作,如下所示。它没有解析 mutate()
调用中 ifelse()
数据帧范围内的名称值,而是仅解析参数的字符值。我能够使用基本函数 get()
来做我想做的事。但是,我一定是混淆了什么,并且正在寻找如何在 rlang/quasiquotation 世界中做到这一点。解释和帮助表示赞赏。
suppressPackageStartupMessages(library(tidyverse))
df <- tibble(x=c(1, NA_integer_, 3), y=101:103)
print(df)
#> # A tibble: 3 x 2
#> x y
#> <dbl> <int>
#> 1 1 101
#> 2 NA 102
#> 3 3 103
# Expected behavior
df %>%
mutate(z = ifelse(is.na(x), y, x))
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <dbl>
#> 1 1 101 1
#> 2 NA 102 102
#> 3 3 103 3
# Similar question seemed to be posted here:
# From: https://community.rstudio.com/t/trouble-with-creating-column-names-from-a-passed-argument-in-function/7819/3
# I expect same output as above, but instead, the column `x` gets filled with the name of the column, not appropriate value.
v_colname <- "x"
df %>%
mutate(z := ifelse(is.na(!!v_colname), y, !!v_colname)) %>%
print()
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <chr>
#> 1 1 101 x
#> 2 NA 102 x
#> 3 3 103 x
# Tried variant with `quo_name()`, same unexpected result:
df %>%
mutate(z := ifelse(is.na(!!quo_name(v_colname)), y, !!quo_name(v_colname)))
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <chr>
#> 1 1 101 x
#> 2 NA 102 x
#> 3 3 103 x
# This works, but I assume I am missing something with quasiquotation semantics:
df %>%
mutate(z := ifelse(is.na(get(v_colname)), y, get(v_colname)))
#> # A tibble: 3 x 3
#> x y z
#> <dbl> <int> <dbl>
#> 1 1 101 1
#> 2 NA 102 102
#> 3 3 103 3
# Session info
sessionInfo()
#> R version 3.5.2 (2018-12-20)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 16299)
#>
#> Matrix products: default
#>
#> locale:
#> [1] LC_COLLATE=English_United States.1252
#> [2] LC_CTYPE=English_United States.1252
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C
#> [5] LC_TIME=English_United States.1252
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] bindrcpp_0.2.2 forcats_0.3.0 stringr_1.3.1 dplyr_0.7.8
#> [5] purrr_0.2.5 readr_1.3.1 tidyr_0.8.2 tibble_2.0.1
#> [9] ggplot2_3.1.0 tidyverse_1.2.1
#>
#> loaded via a namespace (and not attached):
#> [1] Rcpp_1.0.0 cellranger_1.1.0 plyr_1.8.4 pillar_1.3.1
#> [5] compiler_3.5.2 highr_0.7 bindr_0.1.1 tools_3.5.2
#> [9] digest_0.6.18 lubridate_1.7.4 jsonlite_1.6 evaluate_0.12
#> [13] nlme_3.1-137 gtable_0.2.0 lattice_0.20-38 pkgconfig_2.0.2
#> [17] rlang_0.3.1 cli_1.0.1 yaml_2.2.0 haven_2.0.0
#> [21] xfun_0.4 withr_2.1.2 xml2_1.2.0 httr_1.4.0
#> [25] knitr_1.21 hms_0.4.2 generics_0.0.2 grid_3.5.2
#> [29] tidyselect_0.2.5 glue_1.3.0 R6_2.3.0 fansi_0.4.0
#> [33] readxl_1.2.0 rmarkdown_1.11 modelr_0.1.2 magrittr_1.5
#> [37] backports_1.1.3 scales_1.0.0 htmltools_0.3.6 rvest_0.3.2
#> [41] assertthat_0.2.0 colorspace_1.4-0 utf8_1.1.4 stringi_1.2.4
#> [45] lazyeval_0.2.1 munsell_0.5.0 broom_0.5.1 crayon_1.3.4
由 reprex package (v0.2.1)
于 2019-02-27 创建我们可以转换为符号 (sym
) 然后计算 (!!
)
library(dplyr)
df %>%
mutate(z := ifelse(is.na(!!rlang::sym(v_colname)), y, !! rlang::sym(v_colname)))
# A tibble: 3 x 3
# x y z
# <dbl> <int> <dbl>
#1 1 101 1
#2 NA 102 102
#3 3 103 3