有人可以解释一下,我们需要什么!!
,!!!
或者{{}}
需要什么操作员吗rlang
?我试图了解更多有关准引用的知识,但没有得到任何结果。
我已经在 Stack 上找到了几篇关于 curly-curly 运算符的帖子,并且了解我们{{
在将数据帧的变量(或对象的其他子对象)传递到函数中时使用它。但在阅读了有关引用/取消引用的内容后,我对所有这些运算符及其用法完全感到困惑。
为什么我们需要它,为什么有些函数没有它就无法读取参数,最后,它们实际上是如何工作的?
如果您以最简单的方式给出答案,即使我也能理解(也许有例子?),我将不胜感激。
下面我编写了一个snafu()
计算新变量的简单函数snafu_var
。
library(dplyr)
df <- mtcars %>% select(am, cyl) %>% slice(1:5)
snafu <- function(data, var1, var2){
require(dplyr)
var1 <- enquo(var1)
var2 <- enquo(var2)
data %>% mutate(snafu_var = !!var1 + !!var2)
}
snafu(df, var1 = am, var2 = cyl)
Run Code Online (Sandbox Code Playgroud)
现在我想嵌套snafu()
在另一个函数中foobar()
,该函数将利用 . 创建的变量snafu()
。
foobar <- function(data, var1, var2) {
require(dplyr)
data <- snafu(data, var1, var2)
data %>% mutate(foo_var = snafu_var + 1)
}
foobar(df, var1 = am, var2 = cyl)
Run Code Online (Sandbox Code Playgroud)
我在两个问题上苦苦挣扎(可能相关):
1) 中的嵌套函数 …
我正在尝试搜索数据库,然后"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
Run Code Online (Sandbox Code Playgroud)
根据这个讨论,我认为上面的代码可行.而这篇文章引起我去尝试top_n_()
,这似乎不存在.
我正在学习vignette("programming")
哪个有点过头了.这篇文章让我尝试了!! 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 …
Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个自定义函数,在其中使用rlang
's quasiquotation。此函数也在内部使用dplyr
的join
函数。我在下面提供了一个最小的工作示例来说明我的问题。
# needed libraries
library(tidyverse)
# function definition
df_combiner <- function(data, x, group.by) {
# check how many variables were entered for this grouping variable
group.by <- as.list(rlang::quo_squash(rlang::enquo(group.by)))
# based on number of arguments, select `group.by` in cases like `c(cyl)`,
# the first list element after `quo_squash` will be `c` which we don't need,
# but if we pass just `cyl`, there is no `c`, this will take care of that
# issue …
Run Code Online (Sandbox Code Playgroud) 我有一个“月”类型,大致是
\n\nnewtype Month = Month Word8\n
Run Code Online (Sandbox Code Playgroud)\n\nMonth
构造函数未导出的地方;相反,一个函数
mon :: Word8 -> Maybe Month\nmon i = if i > 0 && i < 13\n then Just $ Month i\n else Nothing\n
Run Code Online (Sandbox Code Playgroud)\n\n被导出,仅当输入值在 1 和 12 之间(含 1 和 12)时才会返回一个值。
\n\n现在,使用Language.Haskell.TH.Quote
,我定义了一个准引用 ... 运算符?...这允许我“在编译时”“创建” Month 的实例:
month :: QuasiQuoter\nmonth = QuasiQuoter { quoteDec = error "quoteDec not implemented"\n , quoteType = error "quoteType not implemented"\n , quotePat = "quotePat not implemented"\n , quoteExp = …
Run Code Online (Sandbox Code Playgroud) quasiquoted 列表`(1 ,@2 3)
无效,因为 2 不是列表。但是,`(1 2 ,@3)
是有效的,将返回一个点列表:(1 2 . 3)
。我在 Common Lisp 和 Scheme 中观察到了这个结果。为什么可以在准引用列表的末尾对非列表使用取消引用拼接?为什么结果是点线表?
我怎样才能像这样插值:
{-# LANGUAGE QuasiQuotes #-}
import Text.RawString.QQ
myText :: Text -> Text
myText myVariable = [r|line one
line two
line tree
${ myVariable }
line five|]
myText' :: Text
myText' = myText "line four"
Run Code Online (Sandbox Code Playgroud)
${ myVariable }
作为文字打印,而不是插值,在这种情况下我可以做类似的事情来插值吗?
我需要编写一个dplyr函数来创建自定义面积图。所以这是我的尝试。
area_plot <- function(data, what, by){
by <- ensym(by)
what <- ensym(what)
data %>%
filter(!is.na(!!by)) %>%
group_by(date, !!by) %>%
summarise(!!what := sum(!!what, na.rm = TRUE)) %>%
complete(date, !!by, fill = rlang::list2(!!what := 0)) %>%
ggplot(aes(date, !!what, fill = !!by)) +
geom_area(position = 'stack') +
scale_x_date(breaks = '1 month', date_labels = '%Y-%m', expand = c(.01, .01)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
labs(fill = '')
}
Run Code Online (Sandbox Code Playgroud)
但是我一直想知道是否有任何默认值的by
参数将输出geom_area
所有组的图。我知道我可以if
用来定义ggplot2
首先使用的数据,然后在函数中执行以下操作: …
{{}}
包中的运算符使得rlang
将列名作为函数参数传递(又名准引用)变得非常容易。我理解rlang
是为了使用tidyverse
,但是有没有办法{{}}
使用data.table
?
test_dplyr <- function(dt, col1, col2){
temp <- dt %>%
group_by( {{col2}} ) %>%
summarise(test = mean( {{col1}} ))
return(temp)
}
test_dplyr(dt=iris, col1=Sepal.Length, col2=Species)
> # A tibble: 3 x 2
> Species test
> <fct> <dbl>
> 1 setosa 5.01
> 2 versicolor 5.94
> 3 virginica 6.59
Run Code Online (Sandbox Code Playgroud)
理想情况下,这是我想做的,但它返回一个错误。
test_dt2 <- function(dt, col1, col2){
data.table::setDT(dt)
temp <- dt[, …
Run Code Online (Sandbox Code Playgroud) 我试图将我的头缠在准引号上,以便可以与data.table
电话一起使用。这是一个例子:
library(data.table)
library(rlang)
dt <- data.table(col1 = 1:10, col2 = 11:20)
dt[, col1]
Run Code Online (Sandbox Code Playgroud)
如果我想将其包装到函数中,该怎么做?我试过了:
foo <- function(dt, col) {
col <- quo(col)
expr(dt[, !!col1])
}
foo(dt, col1)
Run Code Online (Sandbox Code Playgroud)
但是得到Error in enexpr(expr) : object 'col1' not found
。我认为我缺少一些步骤,因此data.table
对的评价与有所不同dplyr
。
这个问题与将变量传递给使用 `enquo()` 的函数有关。
我有一个更高的函数,其参数为 tibble ( dat
) 和 dat ( ) 中感兴趣的列variables_of_interest_in_dat
。在该函数中,有一个对我想要传递给的另一个函数的调用variables_of_interest_in_dat
。
higher_function <- function(dat, variables_of_interest_in_dat){
variables_of_interest_in_dat <- enquos(variables_of_interest_in_dat)
lower_function(dat, ???variables_of_interest_in_dat???)
}
lower_function <- function(dat, variables_of_interest_in_dat){
variables_of_interest_in_dat <- enquos(variables_of_interest_in_dat)
dat %>%
select(!!!variables_of_interest_in_dat)
}
Run Code Online (Sandbox Code Playgroud)
传递给 lower_function 的推荐方法是什么variables_of_interest_in_dat
?
我已经尝试过lower_function(dat, !!!variables_of_interest_in_dat)
,但是当我运行时higher_function(mtcars, cyl)
返回“错误:无法!!!
在顶层使用。”
在相关帖子中,higher_function 在将变量传递给 lower 函数之前并未对变量进行 enquo。
谢谢
quasiquotes ×11
r ×8
dplyr ×4
rlang ×4
data.table ×2
haskell ×2
tidyeval ×2
tidyverse ×2
common-lisp ×1
list ×1
quosure ×1
quote ×1
scheme ×1