依赖于R中非标准评估的函数的包装器

时间:2019-04-18 22:14:37

标签: r function subset evaluation ellipsis

我为ftable编写了一个包装器,因为我需要为许多变量计算具有频率和百分比的平面表:

mytable <- function(...) {
    tab <- ftable(...,
                  exclude = NULL)
    prop <- prop.table(x = tab,
                       margin = 2) * 100
    bind <- cbind(as.matrix(x = tab),
                  as.matrix(x = prop))
    margin <- addmargins(A = bind,
                         margin = 1)
    round(x = margin,
          digits = 1)}

# dummy example
mytable(formula = wool + tension ~ breaks,
        data = warpbreaks)

    A_L A_M A_H B_L B_M B_H   A_L   A_M   A_H   B_L   B_M   B_H
10    0   0   1   0   0   0   0.0   0.0  11.1   0.0   0.0   0.0
12    0   1   0   0   0   0   0.0  11.1   0.0   0.0   0.0   0.0
13    0   0   0   0   0   1   0.0   0.0   0.0   0.0   0.0  11.1
14    0   0   0   1   0   0   0.0   0.0   0.0  11.1   0.0   0.0
15    0   0   1   0   0   2   0.0   0.0  11.1   0.0   0.0  22.2
...
Sum   9   9   9   9   9   9 100.0 100.0 100.0 100.0 100.0 100.0

但是,我不能将ftable中的subset参数与函数一起使用,也不能与最小的mytable <- function(...) ftable(...)一起使用:

# dummy example
mytable(formula = wool + tension ~ breaks,
        data = warpbreaks,
        subset = breaks < 20)

 Error in eval(substitute(subset), data, env) : 
  ..3 used in an incorrect context, no ... to look in

我知道我可以使用data = warpbreaks[warpbreaks$breaks < 20, ]作为数据变元的子集,但我希望提高对R的了解。“ Advanced R”帮助我理解错误是由于非标准评估,但我无法纠正我的代码。

所以我的问题是:

  • 如何告诉R在breaks中寻找warpbreaks
  • 更一般地说,是否存在更明显的基本R方法来为单个和多个变量在垂直布局中计算频率和百分比的平面表? (我可以使用mytable(x = warpbreaks$tension, row.vars = 1)获得单个变量的垂直布局)

1 个答案:

答案 0 :(得分:0)

在没有...的函数定义下,出现了另一个错误:

mytable <- function(formula,
                    data,
                    subset) ftable(formula = formula,
                                   data = data,
                                   subset = subset)

mytable(formula = wool + tension ~ breaks,
        data = warpbreaks,
        subset = breaks < 20)

 Error in xj[i] : invalid subscript type 'closure'

此错误使我转向以前没有找到的资源。

Some threads带我去:

# function 1
mytable <- function(...) {
    mc <- match.call()
    mc["exclude"] <- list(NULL)
    do.call(what = ftable,
            args = as.list(x = mc[-1]))
    #etc
}

write.csv系列和lm源代码使我想到了:

# function 2
mytable <- function(...) {
    mc <- match.call()
    mc[[1]] <- quote(expr = ftable)
    mc["exclude"] <- list(NULL)
    eval(expr = mc)
    # etc
}

但是,我正在寻找两种方法(功能1和功能2)的优缺点,因为我不知道某个方法是否值得采用。到目前为止,我发现do.call可能会更慢。

更重要的是,这些方法导致我遇到另一个问题:I can't use my wrapper with lapply and with anymore.