根据对conditional dplyr evaluation的讨论,我想根据传入数据帧中是否存在引用列,有条件地在管道中执行一个步骤。
1)
和2)
产生的结果应该是相同的。
# 1)
mtcars %>%
filter(am == 1) %>%
filter(cyl == 4)
# 2)
mtcars %>%
filter(am == 1) %>%
{
if("cyl" %in% names(.)) filter(cyl == 4) else .
}
# 1)
mtcars %>%
filter(am == 1)
# 2)
mtcars %>%
filter(am == 1) %>%
{
if("absent_column" %in% names(.)) filter(absent_column == 4) else .
}
对于可用列,传递的对象与初始数据帧不对应。原始代码返回错误消息:
filter(cyl == 4)
中的错误:找不到对象'cyl'
我尝试了其他语法(没有运气):
>> mtcars %>%
... filter(am == 1) %>%
... {
... if("cyl" %in% names(.)) filter(.$cyl == 4) else .
... }
Show Traceback
Rerun with Debug
Error in UseMethod("filter_") :
no applicable method for 'filter_' applied to an object of class "logical"
我想扩大这个问题,这个问题可以解释==
电话中filter
右侧的评估。例如,下面的语法试图过滤第一个可用值。 mtcars%>%
filter({
if ("does_not_ex" %in% names(.))
does_not_ex
else
NULL
} == {
if ("does_not_ex" %in% names(.))
unique(.[['does_not_ex']])
else
NULL
})
预计,调用将评估错误消息:
filter_impl(.data, quo)
中的错误:结果的长度必须为32,而不是0
应用于现有列时:
mtcars %>%
filter({
if ("mpg" %in% names(.))
mpg
else
NULL
} == {
if ("mpg" %in% names(.))
unique(.[['mpg']])
else
NULL
})
它使用警告消息:
mpg cyl disp hp drat wt qsec vs am gear carb
1 21 6 160 110 3.9 2.62 16.46 0 1 4 4
警告消息:在
{
中:较长的对象长度不是较短对象长度的倍数
是否有一种扩展现有语法的简洁方法,以便在qazxsw poi调用的右侧获得条件评估,理想情况是保持在dplyr工作流程中?
由于此处作用域的工作方式,您无法从filter
语句中访问数据框。幸运的是,你不需要。
尝试:
if
在这里,您可以在条件中使用'mtcars %>%
filter(am == 1) %>%
filter({if("cyl" %in% names(.)) cyl else NULL} == 4)
'对象,以便检查列是否存在,如果存在,则可以将列返回到.
函数。
编辑:根据docendo discimus'对问题的评论,你可以访问数据框但不是隐含的 - 即你必须用filter
专门引用它
我知道我迟到了,但这里的答案更符合你最初的想法:
.
基本上,你错过了mtcars %>%
filter(am == 1) %>%
{
if("cyl" %in% names(.)) filter(., cyl == 4) else .
}
的.
。请注意这是因为管道没有将filter
添加到.
,因为它位于filter(expr)
包围的表达式中。
编辑:不幸的是,这太好了,不可能
我可能有点迟到了。但是
{}
一个办法?
这段代码可以解决问题并且非常灵活。 ^和$是正则表达式,用于执行完全匹配。
mtcars %>%
filter(am == 1) %>%
try(filter(absent_column== 4))