How to use an unknown number of key columns in a data.table

前端 未结 2 564
后悔当初
后悔当初 2021-01-13 22:08

I want to do the same as explained here, i.e. adding missing rows to a data.table. The only additional difficulty I\'m facing is that I want the number of key columns, i.e.

相关标签:
2条回答
  • 2021-01-13 22:34

    I've never used the data.table package, so forgive me if I miss the mark here, but I think I've got it. There's a lot going on here. Start by reading up on do.call, which allows you to evaluate any function in a sort of non-traditional manner where arguments are specified by a supplied list (where each element is in the list is positionally matched to the function arguments unless explicitly named). Also notice that I had to specify min(df$variable) instead of just min(variable). Read Hadley's page on scoping to get an idea of the issue here.

    CJargs <- lapply(df[, idCols], unique)
    names(CJargs) <- NULL
    CJargs[[length(CJargs) +1]] <- seq(from=min(df$variable), to=max(df$variable))
    DT[do.call("CJ", CJargs),nomatch=NA]
    
    0 讨论(0)
  • 2021-01-13 22:35

    Michael's answer is great. do.call is indeed needed to call CJ flexibly in that way, afaik.

    To clear up on the expression building approach and starting with your code, but removing the df$ parts (not needed and not done in the linked answer, since i is evaluated within the scope of DT) :

    str <- "" 
    for (i in idCols) { 
      str <- paste0(str, "unique(", i, "), ") 
    } 
    str <- paste0(str, "seq(from=min(variable), to=max(variable))") 
    str 
    [1] "unique(fundID), unique(cfType), seq(from=min(variable), to=max(variable))" 
    

    then it's :

    expr <- parse(text=paste0("CJ(",str,")"))
    DT[eval(expr),nomatch=NA]
    

    or alternatively build and eval the whole query dynamically :

    eval(parse(text=paste0("DT[CJ(",str,"),nomatch=NA")))
    

    And if this is done a lot then it may be worth creating yourself a helper function :

    E = function(...) eval(parse(text=paste0(...)))
    

    to reduce it to :

    E("DT[CJ(",str,"),nomatch=NA")
    
    0 讨论(0)
提交回复
热议问题