编辑:%。%运算符现已弃用。使用来自magrittr的%>%。
原始问题
这个%.%
运算符做了什么?
我已经看到它在dplyr软件包中使用了很多,但似乎找不到任何支持文档,说明它是什么或它是如何工作的。
它似乎将命令链接在一起,但据我所知......当我在它时,任何人都可以解释那些与%
符号挂钩的特殊操作符的开局什么时候在技术上是时候使用它们更好地编码?
答案 0 :(得分:19)
我认为哈德利是向你解释的最好的人,但我会试一试。
%.%
是一个名为chain operator的二元运算符。在R
中,您可以使用特殊字符%
来define any binary operator of your own。从我看来,我们几乎用它来制作更容易的“可链接”语法(比如x+y
,比sum(x,y)
好得多)。你可以用它们做很酷的事情,see this cool example here.
%.%
中dplyr
的目的是什么?为了让您更容易表达自己,减少您想要做的事情和表达方式之间的差距。
以introduction to dplyr,为例,假设您想按年,月和日对航班进行分组,选择这些变量加上到达和离开的延迟,按平均值汇总这些变量,然后过滤这些延迟30.如果没有%.%
,你必须这样写:
filter(
summarise(
select(
group_by(hflights, Year, Month, DayofMonth),
Year:DayofMonth, ArrDelay, DepDelay
),
arr = mean(ArrDelay, na.rm = TRUE),
dep = mean(DepDelay, na.rm = TRUE)
),
arr > 30 | dep > 30
)
它完成了这项工作。但要表达自己并阅读它是非常困难的。现在,您可以使用链式运算符%.%
:
hflights %.%
group_by(Year, Month, DayofMonth) %.%
select(Year:DayofMonth, ArrDelay, DepDelay) %.%
summarise(
arr = mean(ArrDelay, na.rm = TRUE),
dep = mean(DepDelay, na.rm = TRUE)
) %.%
filter(arr > 30 | dep > 30)
写和读都比较容易!
这是如何运作的?
我们来看看定义。首先是%.%
:
function (x, y)
{
chain_q(list(substitute(x), substitute(y)), env = parent.frame())
}
它使用另一个名为chain_q
的函数。那么让我们来看看它:
function (calls, env = parent.frame())
{
if (length(calls) == 0)
return()
if (length(calls) == 1)
return(eval(calls[[1]], env))
e <- new.env(parent = env)
e$`__prev` <- eval(calls[[1]], env)
for (call in calls[-1]) {
new_call <- as.call(c(call[[1]], quote(`__prev`), as.list(call[-1])))
e$`__prev` <- eval(new_call, e)
}
e$`__prev`
}
这是做什么的?
为简化起见,我们假设你打电话:group_by(hflights,Year, Month, DayofMonth) %.% select(Year:DayofMonth, ArrDelay, DepDelay)
。
您的来电x
和y
均为group_by(hflights,Year, Month, DayofMonth)
和select(Year:DayofMonth, ArrDelay, DepDelay)
。因此,该函数创建一个名为e
(e <- new.env(parent = env)
)的新环境,并保存一个名为__prev
的对象,并评估第一个调用(e$'__prev' <- eval(calls[[1]], env)
。然后为彼此调用它创建另一个调用,其第一个参数是前一个调用 - 即__prev
- 在我们的例子中它将是select('__prev', Year:DayofMonth, ArrDelay, DepDelay)
- 所以它“链接”循环内的调用。
由于您可以使用二元运算符,因此您实际上可以使用此语法以非常易读的方式表达非常复杂的操作。
答案 1 :(得分:2)
快速搜索让我here:
dplyr
提供了与plyr
相比的另一项创新:使用%.%
运算符从左到右连接操作的能力。这使得dplyr
的行为有点像数据操作的语法。
示例:
Batting %.%
group_by(playerID) %.%
summarise(total = sum(G)) %.%
arrange(desc(total)) %.%
head(5)`
从帮助部分了解更多相关信息,?“%。%”。