根据外部值有条件地应用管道步骤
Posted
技术标签:
【中文标题】根据外部值有条件地应用管道步骤【英文标题】:Conditionally apply pipeline step depending on external value 【发布时间】:2017-10-15 13:13:10 【问题描述】:鉴于 dplyr 工作流程:
require(dplyr)
mtcars %>%
tibble::rownames_to_column(var = "model") %>%
filter(grepl(x = model, pattern = "Merc")) %>%
group_by(am) %>%
summarise(meanMPG = mean(mpg))
我有兴趣根据applyFilter
的值有条件地应用filter
。
解决方案
对于applyFilter <- 1
,使用"Merc"
字符串过滤行,不返回过滤器所有行。
applyFilter <- 1
mtcars %>%
tibble::rownames_to_column(var = "model") %>%
filter(model %in%
if (applyFilter)
rownames(mtcars)[grepl(x = rownames(mtcars), pattern = "Merc")]
else
rownames(mtcars)
) %>%
group_by(am) %>%
summarise(meanMPG = mean(mpg))
问题
建议的解决方案效率低下,因为总是评估 ifelse
调用;一种更理想的方法只会评估applyFilter <- 1
的filter
步骤。
尝试
低效的工作解决方案如下所示:
mtcars %>%
tibble::rownames_to_column(var = "model") %>%
# Only apply filter step if condition is met
if (applyFilter)
filter(grepl(x = model, pattern = "Merc"))
%>%
# Continue
group_by(am) %>%
summarise(meanMPG = mean(mpg))
当然,上面的语法是不正确的。这只是一个说明,理想的工作流程应该是什么样子。
想要的答案
我对创建临时对象不感兴趣;工作流程应该类似于:
startingObject
%>%
...
conditional filter
...
final object
理想情况下,我想找到一个解决方案,我可以控制是否正在评估 filter
调用
【问题讨论】:
基于ifelse()
的解决方案中有一个错误:ifelse(1, rownames(mtcars)[grepl(x = rownames(mtcars), pattern = "Merc")], rownames(mtcars))
给出了[1] "Merc 240D"
,而不是预期的[1] "Merc 240D" "Merc 230" "Merc 280" "Merc 280C" "Merc 450SE" [6] "Merc 450SL" "Merc 450SLC"
。 ifelse()
的值与test
的长度相同。例如,ifelse(c(T, F), 1:3, 4:9)
给出了[1] 1 5
并且没有警告出现了什么问题。
@Aurèle 谢谢,已修复。
【参考方案1】:
这个方法怎么样:
mtcars %>%
tibble::rownames_to_column(var = "model") %>%
filter(if(applyfilter== 1) grepl(x = model, pattern = "Merc") else TRUE) %>%
group_by(am) %>%
summarise(meanMPG = mean(mpg))
这意味着 grepl
仅在 applyfilter 为 1 时才被评估,否则 filter
只会回收 TRUE
。
或者另一种选择是使用:
mtcars %>%
tibble::rownames_to_column(var = "model") %>%
if(applyfilter == 1) filter(., grepl(x = model, pattern = "Merc")) else . %>%
group_by(am) %>%
summarise(meanMPG = mean(mpg))
显然还有另一种可能的方法,您只需打破管道,有条件地进行过滤,然后继续管道(我知道 OP 并没有要求这样做,只是想为其他读者举一个例子)
mtcars %<>%
tibble::rownames_to_column(var = "model")
if(applyfilter == 1) mtcars %<>% filter(grepl(x = model, pattern = "Merc"))
mtcars %>%
group_by(am) %>%
summarise(meanMPG = mean(mpg))
【讨论】:
感谢您的贡献,我想到了一些返回所有T
的方法。我很乐意接受;但是,在实践中,我在考虑是否可以强制dplyr
有条件地跳过 一步。在您的回答中,filter()
被评估为所有T
。
@Konrad,我添加了另一种方法
非常感谢,这很有趣也很有用。
我不知道%<>%
运算符。太好了。以上是关于根据外部值有条件地应用管道步骤的主要内容,如果未能解决你的问题,请参考以下文章