【问题标题】:Dynamic column names in data.tabledata.table 中的动态列名
【发布时间】:2012-07-29 12:26:10
【问题描述】:

我正在尝试向我的data.table 添加列,其中名称是动态的。我还需要在添加这些列时使用by 参数。例如:

test_dtb <- data.table(a = sample(1:100, 100), b = sample(1:100, 100), id = rep(1:10,10))
cn <- parse(text = "blah")
test_dtb[ , eval(cn) := mean(a), by = id]

# Error in `[.data.table`(test_dtb, , `:=`(eval(cn), mean(a)), by = id) : 
#  LHS of := must be a single column name when with=TRUE. When with=FALSE the LHS may be a vector of column names or positions.

另一个尝试:

cn <- "blah"
test_dtb[ , cn := mean(a), by = id, with = FALSE]
# Error in `[.data.table`(test_dtb, , `:=`(cn, mean(a)), by = id, with = FALSE) : 'with' must be TRUE when 'by' or 'keyby' is provided

来自 Matthew 的更新:

这现在适用于 R-Forge 的 v1.8.3。感谢您的强调!
有关新示例,请参阅此类似问题:

Assign multiple columns using data.table, by group

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    来自data.table 1.9.4,您可以这样做:

    ## A parenthesized symbol, `(cn)`, gets evaluated to "blah" before `:=` is carried out
    test_dtb[, (cn) := mean(a), by = id]
    head(test_dtb, 4)
    #     a  b id blah
    # 1: 41 19  1 54.2
    # 2:  4 99  2 50.0
    # 3: 49 85  3 46.7
    # 4: 61  4  4 57.1
    

    查看?:=中的详细信息

    DT[i, (colvector) := val]

    [...] 现在首选 [...] 语法。括号足以阻止 LHS 成为一个符号。同c(colvector)


    原答案:

    您的做法完全正确:在调用[.data.table 时构造要评估的表达式是执行此类操作的data.table 方式。再进一步,为什么不构造一个表达式来评估 整个 j 参数(而不仅仅是它的左侧)?

    这样的事情应该可以解决问题:

    ## Your code so far
    library(data.table)
    test_dtb <- data.table(a=sample(1:100, 100),b=sample(1:100, 100),id=rep(1:10,10))
    cn <- "blah"
    
    ## One solution
    expr <- parse(text = paste0(cn, ":=mean(a)"))
    test_dtb[,eval(expr), by=id]
    
    ## Checking the result
    head(test_dtb, 4)
    #     a  b id blah
    # 1: 30 26  1 38.4
    # 2: 83 82  2 47.4
    # 3: 47 66  3 39.5
    # 4: 87 23  4 65.2
    

    【讨论】:

    • 太棒了,谢谢。我本可以发誓我尝试过这种变化,但显然我没有。非常感谢您的帮助。
    • +1 将此问题的链接添加到FR#2120。似乎有点上头了。
    【解决方案2】:

    表达式可以用 bquote 构造。

    cn <- "blah"
    expr <- bquote(.(as.name(cn)):=mean(a))
    test_dtb[,eval(expr), by=id]
    

    【讨论】:

    • 比做“动态data.table”好多了
    • 很好的答案,非常有用和灵活的方法。 +1!
    【解决方案3】:

    我相信setnames(DT, c(col.names)) 会产生最易读的代码

    【讨论】:

      猜你喜欢
      • 2016-02-02
      • 2013-02-02
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多