[英]How can I use dplyr/magrittr's pipe inside functions in R?
I'm trying to write a function which takes as argument a dataframe and the name of the function. 我正在尝试编写一个函数,它将数据帧和函数的名称作为参数。 When I try to write the function with the standard R syntax, I can get the good result using
eval
and substitute
as recommanded by @hadley in http://adv-r.had.co.nz/Computing-on-the-language.html 当我尝试使用标准R语法编写函数时,我可以使用
eval
获得良好的结果,并在http://adv-r.had.co.nz/Computing-on-the-language中按@hadley的推荐substitute
html的
> df <- data.frame(y = 1:10)
> f <- function(data, x) {
+ out <- mean(eval(expr = substitute(x), envir = data))
+ return(out)
+ }
> f(data = df, x = y)
[1] 5.5
Now, when I try to write the same function using the %>%
operator, it doesn't work : 现在,当我尝试使用
%>%
运算符编写相同的函数时,它不起作用:
> df <- data.frame(y = 1:10)
> f <- function(data, x) {
+ data %>%
+ eval(expr = substitute(x), envir = .) %>%
+ mean()
+ }
> f(data = df, x = y)
Show Traceback
Rerun with Debug
Error in eval(expr, envir, enclos) : objet 'y' introuvable
>
How can I using the combine the piping operator with the use of eval
and substitute
? 如何使用管道操作器与
eval
和substitute
的组合使用? It's seems really tricky for me. 这对我来说似乎很棘手。
A workaround would be 解决方法是
f <- function(data, x) {
v <- substitute(x)
data %>%
eval(expr = v, envir = .) %>%
mean()
}
The problem is that the pipe functions ( %>%
) are creating another level of closure which interferes with the evaluation of substitute(x)
. 问题是管道函数(
%>%
)正在创建另一个级别的闭包,这会干扰substitute(x)
的评估。 You can see the difference with this example 你可以看到这个例子的不同之处
df <- data.frame(y = 1:10)
f1 <- function(data, x) {
print(environment())
eval(expr = environment(), envir = data)
}
f2 <- function(data, x) {
print(environment())
data %>%
eval(expr = environment(), envir = .)
}
f1(data = df, x = y)
# <environment: 0x0000000006388638>
# <environment: 0x0000000006388638>
f2(data = df, x = y)
# <environment: 0x000000000638a4a8>
# <environment: 0x0000000005f91ae0>
Notice how the environments differ in the matrittr version. 请注意matrittr版本中的环境有何不同。 You want to take care of
substitute
stuff as soon as possible when mucking about with non-standard evaluation. 在非标准评估时,你想尽快照顾
substitute
品。
I hope your use case is a bit more complex than your example, because it seems like 我希望你的用例比你的例子更复杂,因为它看起来像
mean(df$y)
would be a much easier bit of code to read. 将是一个更容易阅读的代码。
I've been trying to understand my problem. 我一直在努力理解我的问题。
First, I've written what I want with the summarise()
function : 首先,我用
summarise()
函数编写了我想要的东西:
> library(dplyr)
> df <- data.frame(y = 1:10)
> summarise_(.data = df, mean = ~mean(y))
mean
1 5.5
Then I try to program my own function. 然后我尝试编写自己的函数。 I've found a solution which seems to work with the
lazyeval
package in this post . 我发现这似乎与合作解决
lazyeval
包在这篇文章 。 I use the lazy()
and the interp()
functions to write what I want. 我使用
lazy()
和interp()
函数来编写我想要的东西。
The first possibility is here : 第一种可能性在这里:
> library(lazyeval)
> f <- function(data, col) {
+ col <- lazy(col)
+ inter <- interp(~mean(x), x = col)
+ summarise_(.data = data, mean = inter)
+ }
> f(data = df, col = y)
mean
1 5.5
I can also use pipes : 我也可以使用管道:
> f <- function(data, col) {
+ col <- lazy(col)
+ inter <- interp(~mean(x), x = col)
+ data %>%
+ summarise_(.data = ., mean = inter)
+ }
>
> f(data = df, col = y)
mean
1 5.5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.