使`subset()`在函数中工作

时间:2017-05-30 13:25:02

标签: r

目标是能够使用“子集表达式”(不是逻辑向量)作为用户定义函数的(可选)参数,并使用它来计算数据框的子集。

x <- data.frame(a=1, b=gl(2,5))

f <- function(data, subset) {
    if (!missing(subset))
        data <- subset(data, subset)
    data
}

上面的代码不起作用,

也没有
f <- function(data, subset) {
    if (!missing(subset))
        data <- data[with(data, subset), ]
    data
}

在这两种情况下,我都会在提供subset时收到错误。

> f(x, b == 2)
Error in f(x, b == 2) (from frame.r!322341dM#2) : object 'b' not found

期望的输出:

> f(x)
   a b
1  1 1
2  1 1
3  1 1
4  1 1
5  1 1
6  1 2
7  1 2
8  1 2
9  1 2
10 1 2
> f(x, b == 2)
   a b
6  1 2
7  1 2
8  1 2
9  1 2
10 1 2

2 个答案:

答案 0 :(得分:4)

这个似乎有用。你必须告诉f第二个arg是一个表达式:

f <- function(data, ss) {
    if (!missing(ss)){
        e <- substitute(ss)
        r <- eval(e, data, parent.frame())
        data <- subset(data, r)
    }
    data
}

# > f(x, b == 2)
#    a b
# 6  1 2
# 7  1 2
# 8  1 2
# 9  1 2
# 10 1 2

将参数名称ss替换为subset将无效。我不知道为什么。实际上,我通过浏览subset.data.frame的源代码来提出。

答案 1 :(得分:1)

由于您的功能基本上与subset()具有相同的签名,因此您也可以直接将参数传递给subset()

f <- function(data, ss) {
    if (!missing(ss)){
        call <- unname(match.call())
        call[[1]] <- quote(subset)
        data <- eval(call, parent.frame())
    }
    data
}

此处需要unname(),因为您为此函数提供了与subset()函数不同的参数名称。但基本上我们只是通过调用subset()将调用交换到您的函数。这意味着我们不必做肮脏的工作&#34;在适当的背景下评估过滤器。