How to write a function that calls a function that calls data.table?

前端 未结 2 1962
灰色年华
灰色年华 2020-12-08 16:10

The package data.table has some special syntax that requires one to use expressions as the i and j arguments.

This has some im

相关标签:
2条回答
  • 2020-12-08 16:34

    I think you might be tieing yourself up in knots. This works:

    library(data.table)
    foo <- function(data, by){
      by <- by
      data[, .N, by=by]
    }
    
    DT <- data.table(mtcars)
    foo(DT, 'gear')
    
    plotfoo <- function(data, by){
      foo(data, by)
    }
    plotfoo(DT, 'gear')
    

    And that method supports passing in character values:

    > gg <- 'gear'
    > plotfoo <- function(data, by){
    +   foo(data, by)
    + }
    > plotfoo(DT, gg)
       gear  N
    1:    4 12
    2:    3 15
    3:    5  5
    
    0 讨论(0)
  • 2020-12-08 16:39

    This will work:

    plotfoo <- function(data, by) {
      by <- substitute(by)
      do.call(foo, list(quote(data), by))
    }
    
    plotfoo(DT, gear)
    #    by  N
    # 1:  4 12
    # 2:  3 15
    # 3:  5  5
    

    Explanation:

    The problem is that your call to foo() in plotfoo() looks like one of the following:

    foo(data, eval(by))
    foo(data, by)
    

    When foo processes those calls, it dutifully substitutes for the second formal argument (by) getting as by's value the symbols eval(by) or by. But you want by's value to be gear, as in the call foo(data, gear).

    do.call() solves this problem by evaluating the elements of its second argument before constructing the call that it then evaluates. As a result, when you pass it by, it evaluates it to its value (the symbol gear) before constructing a call that looks (essentially) like this:

    foo(data, gear)
    
    0 讨论(0)
提交回复
热议问题