Reputation: 3339
I was expecting that I could use quasiquotation mechanisms from rlang
package, such as !!
and quo_name()
to program name unquoting within mutate()
and within ifelse()
function. However, it did not work as I expected which I show below. Instead of resolving the value of the name in the scope of the dataframe in the ifelse()
inside the mutate()
call, it resolved only the character value of the parameter. I was able to use the base function get()
to do what I want. However, I must be confusing something, and am looking how to do this in the rlang/quasiquotation world. Explanation and help appreciated.
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
Created on 2019-02-27 by the reprex package (v0.2.1)
Upvotes: 3
Views: 134
Reputation: 887741
We can convert to symbol (sym
) and then evaluate (!!
)
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
Upvotes: 1