我有一个数据框:
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函数生成某些内容,但我真的不知道该怎么做。任何提示都将不胜感激。
答案 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)