将子集和选择与R中的非标准评估相结合

时间:2015-06-05 12:52:23

标签: r

以下是哈德利高级R书中的一个例子:

select <- function(df, vars) {
    vars <- substitute(vars)
    var_pos <- setNames(as.list(seq_along(df)), names(df))
    pos <- eval(vars, var_pos)
    df[, pos, drop = FALSE]
}
select(mtcars, mpg:disp)

我正在尝试将此功能合并到subset2函数中:

subset2 = function(df, cond_expr, vars = "..all") {
    df = df[which(eval(substitute(cond_expr), df, parent.frame())), , drop = FALSE]
    if(vars == "..all") {
        df
    } else {
        browser()
        vars = substitute(vars)
        var_pos = setNames(as.list(seq_along(df)), names(df))
        eprint(var_pos)
        pos = eval(vars, var_pos)
        df[, pos, drop = FALSE]
    }
}
subset2(mtcars, mpg > 24)
subset2(mtcars, mpg > 24, vars = mpg:disp)

行选择仍然有效,但col选择立即失败:

Error in subset2(mtcars, mpg > 24, vars = mpg:disp) : 
  object 'disp' not found 

请注意,我在else分支中插入了browser(),错误建议从未输入分支。

1 个答案:

答案 0 :(得分:0)

此更正适用于我:

subset2 = function(df, cond_expr, vars = "..all") {
  df = df[which(eval(substitute(cond_expr), df, parent.frame())), , drop = FALSE]
  if(substitute(vars) == "..all") {
    df
  } else {
#     browser()
    vars = substitute(vars)
    var_pos = setNames(as.list(seq_along(df)), names(df))
#     eprint(var_pos)
    pos = eval(vars, var_pos)
    df[, pos, drop = FALSE]
  }
}

> subset2(mtcars, mpg > 24, vars = mpg:disp)
                mpg cyl  disp
Merc 240D      24.4   4 146.7
Fiat 128       32.4   4  78.7
Honda Civic    30.4   4  75.7
Toyota Corolla 33.9   4  71.1
Fiat X1-9      27.3   4  79.0
Porsche 914-2  26.0   4 120.3
Lotus Europa   30.4   4  95.1

请注意,我必须使用我无法找到的eprint函数对该行进行评论