我想dplyr::group_by
在另一个函数中使用函数,但我不知道如何将参数传递给这个函数.
有人能提供一个有效的例子吗?
library(dplyr)
data(iris)
iris %.% group_by(Species) %.% summarise(n = n()) #
## Source: local data frame [3 x 2]
## Species n
## 1 virginica 50
## 2 versicolor 50
## 3 setosa 50
mytable0 <- function(x, ...) x %.% group_by(...) %.% summarise(n = n())
mytable0(iris, "Species") # OK
## Source: local data frame [3 x 2]
## Species n
## 1 virginica 50
## 2 versicolor 50
## 3 setosa 50
mytable1 <- function(x, key) x …
Run Code Online (Sandbox Code Playgroud) 在下面的例子中,我们为什么要赞成使用f1
过f2
?从某种意义上说它更有效吗?对于习惯使用R的人来说,使用"substitute + eval"选项似乎更自然.
library(dplyr)
d = data.frame(x = 1:5,
y = rnorm(5))
# using enquo + !!
f1 = function(mydata, myvar) {
m = enquo(myvar)
mydata %>%
mutate(two_y = 2 * !!m)
}
# using substitute + eval
f2 = function(mydata, myvar) {
m = substitute(myvar)
mydata %>%
mutate(two_y = 2 * eval(m))
}
all.equal(d %>% f1(y), d %>% f2(y)) # TRUE
Run Code Online (Sandbox Code Playgroud)
换句话说,除了这个特殊的例子之外,我的问题是:我可以使用dplyr
具有良好的基础R的替代+ eval的NSE函数编程,或者我真的需要学会喜欢所有这些rlang
函数,因为有它的好处(速度,清晰度,组合性......)?
我正在尝试组合一个函数,从我的原始数据框创建一个子集,然后使用dplyr的SELECT和MUTATE根据萼片/花瓣的宽度和长度的总和给出我的大/小条目的数量.
filter <- function (spp, LENGTH, WIDTH) {
d <- subset (iris, subset=iris$Species == spp) # This part seems to work just fine
large <- d %>%
select (LENGTH, WIDTH) %>% # This is where the problem arises.
mutate (sum = LENGTH + WIDTH)
big_samples <- which(large$sum > 4)
return (length(big_samples))
}
Run Code Online (Sandbox Code Playgroud)
基本上,我希望函数返回大花的数量.但是,当我运行该函数时,我得到以下错误 -
filter("virginica", "Sepal.Length", "Sepal.Width")
Error: All select() inputs must resolve to integer column positions.
The following do not:
* LENGTH
* WIDTH
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
library(dplyr) #Devel version, soon-to-be-released 0.6.0
library(tidyr)
library(ggplot2)
library(forcats) #for gss_cat data
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个函数,它结合了即将发布的dplyr
devel版本的quosures tidyr::gather
和ggplot2
.到目前为止它似乎可以使用tidyr
,但我在绘图方面遇到了麻烦.
以下功能似乎适用于tidyr's gather
:
GatherFun<-function(gath){
gath<-enquo(gath)
gss_cat%>%select(relig,marital,race,partyid)%>%
gather(key,value,-!!gath)%>%
count(!!gath,key,value)%>%
mutate(perc=n/sum(n))
}
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何让情节发挥作用.我试着用!!gath
用ggplot2
,但没有奏效.
GatherFun<-function(gath){
gath<-enquo(gath)
gss_cat%>%select(relig,marital,race,partyid)%>%
gather(key,value,-!!gath)%>%
count(!!gath,key,value)%>%
mutate(perc=n/sum(n))%>%
ggplot(aes(x=value,y=perc,fill=!!gath))+
geom_col()+
facet_wrap(~key, scales = "free") +
geom_text(aes(x = "value", y = "perc",
label = "perc", group = !!gath),
position = position_stack(vjust = .05))
}
Run Code Online (Sandbox Code Playgroud) 我对如何将函数参数传递给dplyr和ggplot代码感到困惑.我正在使用最新版本的dplyr和ggplot2这是我的代码来生成一个条形图(清晰度与平均价格)
diamond.plot<- function (data, group, metric) {
group<- quo(group)
metric<- quo(metric)
data() %>% group_by(!! group) %>%
summarise(price=mean(!! metric)) %>%
ggplot(aes(x=!! group,y=price))+
geom_bar(stat='identity')
}
diamond.plot(diamonds, group='clarity', metric='price')
Run Code Online (Sandbox Code Playgroud)
错误:
Error in UseMethod("group_by_") : no applicable method for 'group_by_' applied to an object of class "packageIQR"
Run Code Online (Sandbox Code Playgroud)
对于最新版本的dplyr,强调不推荐使用强调的verbs_().好像我们应该使用quosures.
我的问题:
上面的代码出了什么问题?(没有下划线dplyr动词请..)
在ggplot中,我知道我们可以使用aes_string(),但在我的例子中,只有一个参数在aes中从函数参数传递.
提前致谢.
我最近注意到这rlang::sym
似乎不适用于匿名函数,我不明白为什么.这是一个例子,它非常笨拙和丑陋,但我认为它说明了这一点
require(tidyverse)
data <- tibble(x1 = letters[1:3],
x2 = letters[4:6],
val = 1:3)
get_it <- function(a, b){
data %>%
mutate(y1 = !!rlang::sym(a)) %>%
mutate(y2 = !!rlang::sym(b)) %>%
select(y1, y2, val)
}
get_it("x1", "x2")
Run Code Online (Sandbox Code Playgroud)
这定义了一些玩具数据和一个(可怕的)函数,它基本上根据列名重命名列.现在我可以为a和b的不同组合做同样的事情:
d <- tibble(x = c("x1", "x2"),
y = c("x2", "x1"))
d %>% mutate(tmp = map2(x, y, get_it))
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用匿名函数执行完全相同的操作,则它不起作用:
d %>% mutate(tmp = map2(x, y, function(a, b){
data %>%
mutate(y1 = !!rlang::sym(a)) %>%
mutate(y2 = !!rlang::sym(b)) %>%
select(y1, y2, val)
}))
Run Code Online (Sandbox Code Playgroud)
object 'a' not found …
I\'m currently co-developing an R
package using devtools
. We use the\ntidyverse %>%
and associated purrr
and dplyr
packages within our\nfunctions.
One of our functions is as follows (edited for clarity):
\n#\' Print `cust_modl` object\n#\'\n#\' @param x A `cust_modl` object.\n#\' @param ... Additional arguments passed to `print.cust_modl()` to print the\n#\' object.\n#\'\n#\' @method print cust_modl\n#\' @export\nprint.cust_modl <- function(x, ...) {\n\nreq_var_nms <- x$var %>%\npurrr::compact(.x = .) %>%\nnames(x = .)\n\ncomp_var_ind_filt <- req_var_nms %>%\npurrr::map(.x = ., .f = ~ purrr::pluck(x$var, .x))\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n … 前言
我通常dplyr
在我的包中使用.在此之前0.7.0
,我使用dplyr
动词的强调版本来避免在注释期间R CMD CHECK
.例如,代码:
x <- tibble::tibble(v = 1:3, w = 2)
y <- dplyr::filter(x, v > w)
Run Code Online (Sandbox Code Playgroud)
本来会产生这样的R CMD CHECK
说明:
* checking R code for possible problems ... NOTE
no visible binding for global variable ‘v’
Run Code Online (Sandbox Code Playgroud)
相比之下,使用标准评估版:
y <- dplyr::filter_(x, ~v > w)
Run Code Online (Sandbox Code Playgroud)
没有发出这样的说明.
但是,使用dplyr编程dplyr 0.7.0
的插图表示在包中包含函数的适当语法(以避免注释)是:dplyr
y <- dplyr::filter(x, .data$v > .data$w)
Run Code Online (Sandbox Code Playgroud)
因此,新闻文件说"不再需要每个主要动词的强调版本,因此这些功能已被弃用(但为了向后兼容性而保持不变)."
题
小插图说上面的新语法不会产生R CMD check
NOTES,"只要你还导入rlang::.data
了@importFrom rlang …
我正在编写一个使用 tidyeval 的包。因为我使用 tidyeval 我在描述文件的导入下列出了 rlang。
其中一个函数包含几行使用 :=
像这样:
data %>%
dplyr::mutate(
!!New_R := AP_R_X*!!X + AP_R_Y*!!Y + AP_R_Z*!!Z,
!!New_U := AP_U_X*!!X + AP_U_Y*!!Y + AP_U_Z*!!Z,
!!New_F := AP_F_X*!!X + AP_F_Y*!!Y + AP_F_Z*!!Z)
Run Code Online (Sandbox Code Playgroud)
该代码按预期工作,但在运行时收到以下注释 devtools::check()
no visible global function definition for ':='
Run Code Online (Sandbox Code Playgroud)
我怎样才能摆脱这个笔记?这不是 rlang 评估的一部分吗?
编辑:我已经阅读了问题“没有可见的 'median' 全局函数定义,尽管那里的答案解释了为什么会出现这样的问题。它没有解释为什么:=
在我导入时没有定义rlang
。我已经编辑了这个问题来制作这个更清楚。
考虑一个小标题,其中每一列都是可以采用许多值的字符向量-假设是“ A”到“ F”。
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
Run Code Online (Sandbox Code Playgroud)
我希望创建一个函数,该函数将列名作为参数,并重新编码该列,以使任何答案“ A”都变为NA,否则将按原样返回df。以这种方式设计它的原因是适合于使用给定列执行一系列操作的更广泛的管道。
有很多方法可以做到这一点。但是我有兴趣了解最佳的惯用tidy_eval / tidyverse方法是什么。首先,问题名称必须位于变异动词的左侧,因此我们适当地使用!!
and :=
运算符。但是,那该放在右边呢?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
Run Code Online (Sandbox Code Playgroud)
我最初的想法是,这将起作用:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
Run Code Online (Sandbox Code Playgroud)
但是,当然,函数内部的爆炸只是返回文字字符串(例如“ q1”)。我最终采取了一种感觉很拙劣的方法,即使用基本R [[
运算符并依靠.
dplyr 的构造来在右侧引用数据,并且它起作用了,因此从某种意义上说,我已经解决了我的根本问题:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
Run Code Online (Sandbox Code Playgroud)
我有兴趣从精通tidyeval的人那里获得反馈,以了解是否有更惯用的方法来执行此操作,希望看到一个可行的示例可以增强我对tidyeval函数集的更一般的理解。有什么想法吗?