简体   繁体   English

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

[英]Wrapper for a function relying on non-standard evaluation in R

I wrote a wrapper around ftable because I need to compute flat tables with frequency and percentage for many variables: 我写了一个围绕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)
}

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

However, I can not use the subset argument from ftable with my function, nor with the minimal mytable <- function(...) ftable(...) : 但是,我不能使用ftable的子参数和我的函数,也不能使用minimal mytable <- function(...) ftable(...)

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

I know I can subset in the data argument with data = warpbreaks[warpbreaks$breaks < 20, ] as a workaround, but I am looking to improve my knowledge of R. " Advanced R " helped me to understand that the error is due to non-standard evaluation, but I did not manage to correct my code. 我知道我可以使用data = warpbreaks[warpbreaks$breaks < 20, ]作为解决方法在data参数中进行子集化,但我希望提高我对R的了解。“ Advanced R ”帮助我理解错误是由于非标准的评估,但我没有设法纠正我的代码。

So my questions are: 所以我的问题是:

  • How can I tell R to look for breaks in warpbreaks ? 我如何告诉R在warpbreaks寻找breaks
  • More generally, is there a more obvious base R way to compute flat tables with frequency and percentage in a vertical layout for both single and multiple variables ? 更一般地说,单个和多个变量的垂直布局中是否有更明显的基本R方式来计算具有频率和百分比的平面表? (I can get a vertical layout for a single variable with mytable(x = warpbreaks$tension, row.vars = 1) .) (我可以使用mytable(x = warpbreaks$tension, row.vars = 1)获得单个变量的垂直布局mytable(x = warpbreaks$tension, row.vars = 1) 。)

With a function definition without ... , I get a different error: 使用没有...的函数定义,我得到一个不同的错误:

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'

This error led me to ressources I havent found before. 这个错误导致我以前找不到的资源。

Some threads led me to: 有些 线索让我:

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

The write.csv family and lm source code led me to: write.csv系列和lm源代码使我:

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

However, I am looking for pro and cons of both methods (function 1 and function 2), because I do not know if a method is to be favored. 但是,我正在寻找两种方法(功能1和功能2)的优点和缺点,因为我不知道某种方法是否受到青睐。 So far I just found that do.call might be slower. 到目前为止,我刚发现do.call可能会变慢。

More importantly, these methods led my to another issue: I can not use my wrapper with lapply and with anymore. 更重要的是,这些方法导致我到另一个问题: 我不能用我的包装与lapplywith了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM