9

可能重复:
如何编写一个 R 函数来评估数据框中的表达式

我想编写一个对 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 这样的包中看到这种“魔法”。有什么诀窍?

4

2 回答 2

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)
于 2012-10-11T18:17:16.727 回答
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)
于 2012-10-11T18:17:18.163 回答