通过改变条件数来过滤R中的数据帧

时间:2014-12-19 01:49:04

标签: r filtering apply

我有一个数据框:

 a <- c(1,2,3)
 b <- c(4,5,6)
 c <- c(7,8,9)
 d <- c(10,11,12)
 e <- data.frame(a=a,b=b,c=c,d=d)
 #e
 #  a b c  d
 #1 1 4 7 10
 #2 2 5 8 11
 #3 3 6 9 12

我想指定一个条件列表来过滤数据框(我意识到这个例子很傻,但请耐心等待。)

我想创建一个函数,我可以在其中输入不同数量的条件,并将条件适用的行作为输出。

例如,如果我输入一个列表:

condition <- list('a'=3,'b'=6)

那就意味着我想要:

e[e[,'a'] == 3 & e[,'b'] == 6,]
#  a b c  d
#3 3 6 9 12

我试图把它输入一个字符串

st <- "e[,'a'] == 3 & e[,'b'] == 6"
e[get(st),]

这会产生错误。

我认为可以使用apply函数生成某些内容,但我真的不知道该怎么做。任何提示都将不胜感激。

4 个答案:

答案 0 :(得分:3)

您可以使用表达式,例如

conds <- list(W = as.name("a"), X = 3, Y = as.name("b"), Z = 6)
expr <- substitute(W == X & Y == Z, env = conds)    
e[with(e, eval(expr)), ]
#   a b c  d
# 3 3 6 9 12

您还可以使用Hadley的lazyeval包,该包非常有趣且易于使用。我们可以创建一个与dplyr::filter

类似的函数
library(lazyeval)

fun <- function(.data, ...) {
    dots <- lazy_dots(...)
    .data[lazy_eval(dots, data = .data)[[1]], ]
}

fun(e, a == 3 & b == 6)
#   a b c  d
# 3 3 6 9 12

答案 1 :(得分:2)

st字符串示例正常工作的方式是eval(parse()),但通常不建议这样做。 (有关为什么这是一个坏主意的详细信息,请参见此处:What specifically are the dangers of eval(parse(...))?。)

> e[eval(parse(text = st)), ]
  a b c  d
3 3 6 9 12

如果你可以分享更多的上下文,那么提出替代解决方案会更容易。你的条件清单是什么?

你可以像@thelatemail评论的那样,把它想象成一个连接操作(你的condition正在工作,因为data.frame是一个列表),使它明确地成为一个data.frame:

condition.df <- data.frame(a = 3, b = 6)
merge(e, condition.df)

答案 2 :(得分:2)

 e[ eval( parse(text= paste(names(condition), "==", condition, 
                                      sep=" ", collapse="&")) ) , ]
#---------
  a b c  d
3 3 6 9 12

你可以作为eval的envir = e参数来使它更安全&#34;。

答案 3 :(得分:1)

如果需要,您可以为函数添加参数,但这会复制您尝试执行的操作。

    foo <- function(data, column1, x, column2, y){
      out <- data[data[, column1] == x & data[, column2] == y, ]
      return(out)
    }

    foo(dF, "a", 3, "b", 6)