dplyr()中的非标准评估和准引用无法正常运行({天真)

时间:2018-08-08 03:35:03

标签: r dplyr tidyeval non-standard-evaluation quasiquotes

我正在尝试搜索数据库,然后用以下原始示例中的原始搜索"derived_name"派生名称来标记输出。我正在使用dplyr管道%>%,但在准报价和/或非标准评估方面遇到了麻烦。具体来说,使用count_colname,在最后一个"derived_name"函数中,从top_n()派生的字符对象无法对数据帧进行子集化。

search_name <- "derived_name"
set.seed(1)
letrs <- letters[rnorm(52, 13.5, 5)]
letrs_count.df <- letrs %>%
    table() %>%
    as.data.frame()
count_colname <- paste0(search_name, "_letr_count")
colnames(letrs_count.df) <- c("letr", count_colname)
letrs_top.df <- letrs_count.df %>%
    top_n(5, count_colname)
identical(letrs_top.df, letrs_count.df)
# [1] TRUE

基于this discussion,我认为上面的代码可以工作。 this post使我尝试了top_n_(),它似乎不存在。

我正在研究vignette("programming"),这有点烦人。 This post使我尝试使用!! sym()语法,该语法有效,但是我不知道为什么!帮助理解下面的代码为什么起作用,将不胜感激。谢谢。

colnames(letrs_count.df) <- c("letr", count_colname)
letrs_top.df <- letrs_count.df %>%
    top_n(5, (!! sym(count_colname)))
letrs_top.df
#   letr derived_name_letr_count
# 1    l                       5
# 2    m                       6
# 3    o                       7
# 4    p                       5
# 5    q                       6

以下基于@lionel和@Tung的问题和评论的其他令人困惑的示例。这里让我感到困惑的是,帮助文件说sym()“将字符串作为输入并将其转换为符号”和!!“取消引用其参数”。但是,在下面的示例中,sym(count_colname)似乎未引用derived_name_letr_count。我不明白为什么{{1}中需要!!,因为!! sym(count_colname)sym(count_colname)给出相同的值。

qq_show(!! sym(count_colname))

2 个答案:

答案 0 :(得分:5)

根据top_n文档(?top_n),它不支持character / string输入,因此第一个示例不起作用。在您的第二个示例中,rlang::sym将字符串转换为变量名,然后!!取消引号,以便可以在top_n中对其进行求值。注意:top_n和其他dplyr verbs自动引用其输入。

使用@lionel建议的rlang::qq_show,我们可以看到它不起作用,因为count_colname中没有letrs_count.df

library(tidyverse)

set.seed(1)
letrs <- letters[rnorm(52, 13.5, 5)]
letrs_count.df <- letrs %>%
  table() %>%
  as.data.frame()

search_name <- "derived_name"
count_colname <- paste0(search_name, "_letr_count")
colnames(letrs_count.df) <- c("letr", count_colname)
letrs_count.df
#>    letr derived_name_letr_count
#> 1     b                       1
#> 2     c                       1
#> 3     f                       2
...

rlang::qq_show(top_n(letrs_count.df, 5, count_colname))
#> top_n(letrs_count.df, 5, count_colname)

sym!!创建letrs_count.df中存在的右列名称

rlang::qq_show(top_n(letrs_count.df, 5, !! sym(count_colname)))
#> top_n(letrs_count.df, 5, derived_name_letr_count)

letrs_count.df %>%
  top_n(5, !! sym(count_colname))
#>   letr derived_name_letr_count
#> 1    l                       5
#> 2    m                       6
#> 3    o                       7
#> 4    p                       5
#> 5    q                       6

top_n(x, n, wt)

参数:

  • x:要过滤的tbl()

  • n:要返回的行数。如果x被分组,则这是每组的行数。如果有联系,将包括多于n行。如果n为正,则选择前n行。如果为负,则选择底部的n行。

  • wt :(可选)。用于订购的变量。如果未指定,则默认为tbl中的最后一个变量。 该自变量会自动加引号,然后在数据框的上下文中进行求值。它支持取消报价。有关这些概念的介绍,请参见vignette("programming")

另请参阅以下答案:1st2nd3rd

答案 1 :(得分:0)

因此,我意识到我在这个问题(以及许多其他问题)中苦苦挣扎的并不是真正的准报价和/或非标准评估,而是converting character strings into object names。这是我的新解决方案:

letrs_top.df <- letrs_count.df %>%
    top_n(5, get(count_colname))