dplyr :: mutate中的非标准eval

时间:2018-04-17 16:06:34

标签: r dplyr tidyverse

理论上这应该有效,因为我已经阅读过关于NSE的tidyverse指南,但它给我一个错误,如本例底部所示。为什么是这样?我理解如何对对象进行简单的quasiquotation,但我不明白如何评估两个quasiquoted对象的一小部分。任何人都可以帮忙吗?

    tmp <- structure(list(qa11a = structure(c(1616, 7293, 1528, 1219, 2049, 286),
                                            label = "Total voters removed from Nov. 2008 to Nov. 2010",
                                            class = c("labelled","numeric")),
                          state_abbv = c("AL", "AL", "AL", "AL", "AL", "AL"),
                          fipscode = c("0100100000", "0100300000", "0100500000",
                                       "0100700000", "0100900000", "0101100000"),
                          qa1a = structure(c(34727, 114952, 16450, 12239, 31874, 7650),
                                           label = "Total registered & eligible to vote November 2010",
                                           class = c("labelled", "numeric")),
                          reg.pct = structure(c(0.0465343968669911, 0.0634438722249287,
                                                0.092887537993921, 0.0995996404935044,
                                                0.0642843697057163, 0.0373856209150327),
                                              label = "Total voters removed from Nov. 2008 to Nov. 2010",
                                              class = c("labelled", "numeric")),
                          precleared = c(1, 1, 1, 1, 1, 1),
                          year = c(2010, 2010, 2010, 2010, 2010, 2010),
                          shelby = c(0, 0, 0, 0, 0, 0), 
                          pres = c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)),
                      .Names = c("qa11a", "state_abbv", "fipscode", "qa1a",
                                 "reg.pct", "precleared", "year", "shelby", "pres"),
                      row.names = c(NA, -6L),
                      class = c("tbl_df", "tbl", "data.frame"))

    require(tidyverse)
    require(rlang)

    upper="qa11a"
    lower="qa1a"
    pct.name="rej.reg"

    pct.reg <- quo_name(enquo(pct.name))
    upper <- enquo(upper)
    lower <- enquo(lower)

    h <- tmp %>%
        mutate(!! pct.reg := (!!upper)/(!!lower))

    #> Error in mutate_impl(.data, dots): Evaluation error: non-numeric argument to binary operator.

1 个答案:

答案 0 :(得分:3)

我们可以将字符串转换为符号,然后评估

tmp %>% 
   mutate(!! pct.name := (!! sym(upper)/(!! sym(lower))))
# A tibble: 6 x 10
#  qa11a state_abbv fipscode     qa1a reg.pct precleared  year shelby pres  rej.reg
#  <dbl> <chr>      <chr>       <dbl>   <dbl>      <dbl> <dbl>  <dbl> <lgl>   <dbl>
#1  1616 AL         0100100000  34727  0.0465       1.00  2010      0 F      0.0465
#2  7293 AL         0100300000 114952  0.0634       1.00  2010      0 F      0.0634
#3  1528 AL         0100500000  16450  0.0929       1.00  2010      0 F      0.0929
#4  1219 AL         0100700000  12239  0.0996       1.00  2010      0 F      0.0996
#5  2049 AL         0100900000  31874  0.0643       1.00  2010      0 F      0.0643
#6   286 AL         0101100000   7650  0.0374       1.00  2010      0 F      0.0374

当我们对字符串应用enquo时,它将转换为带引号

的quosure
enquo(upper)
# <quosure>
#  expr: ^"qa11a"
#  env:  empty

不是从字符串转换,而是更容易做

upper <- quo(qalla)
lower <- quo(qala)

在OP的代码中,调用enquo,即在字符串对象上转换为quosure将导致字符串quosure并且不打算

upper <- "qa11a"
lower <- "qa1a"
enquo(upper)
#<quosure>
#  expr: ^"qa11a"
#  env:  empty

我们可以将它与

进行比较
upper <- quo(qa11a)
lower <- quo(qa1a)
upper
# <quosure>
#  expr: ^qalla
#  env:  global

并执行它

tmp %>% 
     mutate(!! pct.name := (!! upper)/ (!! lower))
# A tibble: 6 x 10
#  qa11a state_abbv fipscode     qa1a reg.pct precleared  year shelby pres  rej.reg
#  <dbl> <chr>      <chr>       <dbl>   <dbl>      <dbl> <dbl>  <dbl> <lgl>   <dbl>
#1  1616 AL         0100100000  34727  0.0465       1.00  2010      0 F      0.0465
#2  7293 AL         0100300000 114952  0.0634       1.00  2010      0 F      0.0634
#3  1528 AL         0100500000  16450  0.0929       1.00  2010      0 F      0.0929
#4  1219 AL         0100700000  12239  0.0996       1.00  2010      0 F      0.0996
#5  2049 AL         0100900000  31874  0.0643       1.00  2010      0 F      0.0643
#6   286 AL         0101100000   7650  0.0374       1.00  2010      0 F      0.0374