可能重复:
How to write an R function that evaluates an expression within a data-frame
我想编写一个对data.frame进行排序的函数 - 而不是使用繁琐的order()。给出像
这样的东西> x=data.frame(a=c(5,6,7),b=c(3,5,1))
> x
a b
1 5 3
2 6 5
3 7 1
我想说的是:
sort.df(x,b)
所以这是我的功能:
sort.df <- function(df, ...) {
with(df, df[order(...),])
}
我为此感到自豪。鉴于R的懒惰评估,我认为......参数只会在需要时进行评估 - 到那时它将在范围内,因为'with'。
如果我直接运行'with'行,它就可以了。但功能没有。
> with(x,x[order(b),])
a b
3 7 1
1 5 3
2 6 5
> sort.df(x,b)
Error in order(...) : object 'b' not found
出了什么问题以及如何解决?例如,我经常在像plyr这样的软件包中看到这种“魔力”。有什么诀窍?
答案 0 :(得分:9)
这将做你想要的:
sort.df <- function(df, ...) {
dots <- as.list(substitute(list(...)))[-1]
ord <- with(df, do.call(order, dots))
df[ord,]
}
## Try it out
x <- data.frame(a=1:10, b=rep(1:2, length=10), c=rep(1:3, length=10))
sort.df(x, b, c)
这样:
sort.df2 <- function(df, ...) {
cl <- substitute(list(...))
cl[[1]] <- as.symbol("order")
df[eval(cl, envir=df),]
}
sort.df2(x, b, c)
答案 1 :(得分:7)
这是因为当你通过b时,你实际上并没有传递一个物体。在你的函数中添加一个browser
,你会明白我的意思。我从某个互联网机器人那里偷了这个:
x=data.frame(a=c(5,6,7),b=c(3,5,1))
sort.df <- function(df, ..., drop = TRUE){
ord <- eval(substitute(order(...)), envir = df, enclos = parent.frame())
return(df[ord, , drop = drop])
}
sort.df(x, b)
会奏效。
如果您正在寻找一种在应用意义上做到这一点的好方法,那么
library(taRifx)
sort(x, f=~b)