【问题标题】:Vectorise assignment of R data.table cells with column differing by row向量化分配 R data.table 单元格,其列因行而异
【发布时间】:2017-09-03 00:59:27
【问题描述】:

我在思考如何通过引用有效地分配 data.table 的各个单元格时遇到问题。每列(除 id 外)都表示该主题在特定日期的状态。

为了便于说明,每行要切换的列存储在单独的列表或向量中。下面的 for 循环完成了这项工作,但实际数据非常大(因此也通过引用进行分配),更本地的解决方案将是理想的。

dt = data.table(id = letters[1:5],
                `1`=0,`2`=0,`3`=0)

d = c(3,2,1,2,3)

for (i in 1:nrow(dt)) {
  print(d[i])
  dt[i,1+d[i] := 1]
}

print(dt)
# id 1 2 3
# 1:  a 0 0 1
# 2:  b 0 1 0
# 3:  c 1 0 0
# 4:  d 0 1 0
# 5:  e 0 0 1

我尝试使用 .SD 或 .I 的一切都失败了,也许有人可以指出我正确的方向?

例如

dt[,d[.I] := 1]

【问题讨论】:

    标签: r data.table vectorization


    【解决方案1】:

    我会在 for 循环中为列而不是行使用 set:=

    for(i in seq_along(dt)[-1]){
        set(dt, NULL, i, 0 + (d == i - 1))
    }
    dt
    #    id 1 2 3
    # 1:  a 0 0 1
    # 2:  b 0 1 0
    # 3:  c 1 0 0
    # 4:  d 0 1 0
    # 5:  e 0 0 1
    

    【讨论】:

    • 注意到set 也是data.table 中的update by reference 运算符
    【解决方案2】:

    另一种方法是从ids 的data.table 和状态向量开始,然后重塑

    dt <- data.table(id = letters[1:5], state = d)
    #    id state
    # 1:  a     3
    # 2:  b     2
    # 3:  c     1
    # 4:  d     2
    # 5:  e     3
    
    dcast(dt, id ~ state, fun.aggregate = length)
    
    #    id 1 2 3
    # 1:  a 0 0 1
    # 2:  b 0 1 0
    # 3:  c 1 0 0
    # 4:  d 0 1 0
    # 5:  e 0 0 1
    

    【讨论】:

      【解决方案3】:

      base R 方法是使用 row/column 索引

      setDF(dt)
      dt[-1][cbind(seq_len(nrow(dt)), d)] <- 1
      dt
      #  id 1 2 3
      #1  a 0 0 1
      #2  b 0 1 0
      #3  c 1 0 0
      #4  d 0 1 0
      #5  e 0 0 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多