do.call与过滤功能

时间:2015-09-11 23:06:21

标签: r dplyr

我希望能够将搜索参数动态传递给dplyr的过滤器功能。我可以手动进行这样的搜索:

filter(df, sex=='F', country=='USA')

但我需要能够动态地执行此操作。

我试过do.call,就像这样:

do.call('filter',list(df,country=='USA'))

但这给了我一个错误:

  

找不到对象国家

如果我将国家/地区放在引号中,我没有收到错误但我没有从过滤器中获得任何结果。

3 个答案:

答案 0 :(得分:4)

根据aosmith的建议,我提出了:

 df <- data.frame(
          sex = sample(c('M','F'),10, replace = TRUE),
          country = sample(c('USA','UK'),10, replace = TRUE)
                 )

 filter_criteria <- ~ country == 'USA'
 do.call(filter_,list(df,filter_criteria))

答案 1 :(得分:1)

我看到该请求希望能够拥有多个条件。我需要使用个别标准的字符表示,paste使用“&amp;”让这成功。尝试了几种使用具有一致失败的公式对象的不同方法:

filter_criterion1 <- "country == 'USA'"
filter_criterion2 <- "sex == 'F'"
do.call(filter_, list(df,paste(filter_criterion2, filter_criterion1, sep="&")))
  sex country
1   F     USA
2   F     USA
3   F     USA

感谢aosmith指出.dots参数将接受字符或公式规范的列表:

  do.call(filter_, list(df,.dots=list(filter_criterion2, filter_criterion1)))
  sex country
1   F     USA
2   F     USA
3   F     USA

答案 2 :(得分:1)

我最近在使用包 lazyeval 的情况下使用Shiny(请参阅答案here)在动态情境中使用filter_。取决于您正在做什么,它可能是相关的,尽管您的实际情况可能更简单。

你可以通过创建一个你想要调节的变量向量和相同长度的向量以及每个变量的条件来做类似的事情。

library(lazyeval)

variables = c("country", "sex")
conditions = c("USA", "F")

然后,您可以循环遍历变量/条件,使用interp创建要筛选的条件列表。

dots = lapply(1:length(variables),
             function(crit) interp(~y == z, 
                                .values = list(y = as.name(variables[crit]), 
                                            z = conditions[crit])))
dots
[[1]]
~country == "USA"
<environment: 0x02eed660>

[[2]]
~sex == "F"
<environment: 0x02c6b388>

然后只使用.dots filter参数中的结果列表。我在这里使用@ joshuagordon&#39; s df

filter_(df, .dots = dots)
  sex country
1   F     USA
2   F     USA
3   F     USA
4   F     USA