【问题标题】:replace values in data-table based on column number and separate index vector根据列号和单独的索引向量替换数据表中的值
【发布时间】:2023-03-09 15:57:01
【问题描述】:

我有一个大数据表,我需要根据列号和取决于行号的索引将单元格设置为固定值(例如 0)。

作为一个例子,我得到了一个数据表“dt”,里面全是 1。此外,我有一个列向量,给出保持不变的列数(每行),其余列数应设置为 0。

dt <- setnames(data.table(matrix(1,nrow=100, ncol=11)),as.character(c(0:10)))

set.seed(1)
index <- sample(c(0:11),100, replace=TRUE)

> dput(index)
c(3L, 4L, 6L, 10L, 2L, 10L, 11L, 7L, 7L, 0L, 2L, 2L, 8L, 4L, 
9L, 5L, 8L, 11L, 4L, 9L, 11L, 2L, 7L, 1L, 3L, 4L, 0L, 4L, 10L, 
4L, 5L, 7L, 5L, 2L, 9L, 8L, 9L, 1L, 8L, 4L, 9L, 7L, 9L, 6L, 6L, 
9L, 0L, 5L, 8L, 8L, 5L, 10L, 5L, 2L, 0L, 1L, 3L, 6L, 7L, 4L, 
10L, 3L, 5L, 3L, 7L, 3L, 5L, 9L, 1L, 10L, 4L, 10L, 4L, 4L, 5L, 
10L, 10L, 4L, 9L, 11L, 5L, 8L, 4L, 3L, 9L, 2L, 8L, 1L, 2L, 1L, 
2L, 0L, 7L, 10L, 9L, 9L, 5L, 4L, 9L, 7L)

例如在第一行中,前三个单元格保持不变,其他单元格设置为 0。 由于它是一个大型数据表,我正在寻找一种有效的方法来做到这一点

【问题讨论】:

  • set.seed() 在创建随机数据以实现可重复性之前
  • 感谢您的评论。我确实做到了,但忘了在这里复制它;)

标签: r data.table


【解决方案1】:

使用Matrix 包的选项:

library(Matrix)
mat <- as.matrix(dt)
mat * as.matrix(sparseMatrix(
    i=rep(seq_along(index), index),
    j=unlist(sapply(index, seq_len)), 
    x=1))

或者使用data.table::set:

for (j in seq_along(names(dt)))
    set(dt, which(j>index), j, 0)

【讨论】:

  • 我实际上采用了 data.table::set 的解决方案。结果证明这是当前建议中最快的一个。
【解决方案2】:

为了避免复杂性,我采取了相反的方法,首先将所有 1 更改为 0。然后是一个双 for 循环,将索引中指示的列数更改为 1s:

library(data.table)

dt <- setnames(data.table(matrix(0,nrow=100, ncol=11)),as.character(c(0:10)))

index <- sample(c(0:11),100, replace=TRUE)

for(i in 1:length(index)) {
  if (index[i] > 0) {
    for(j in 1:index[i]) {
      dt[i,j] <- 1
    }
  }
}

【讨论】:

  • set(dt, i, j, 1)替换dt[i,j] &lt;- 1,应该很快,否则会非常慢
【解决方案3】:
last_col <- names(dt)[ncol(dt)]
for (r in seq_len(nrow(dt))) {
  zero_from <- max(index[r]-1L, 0L)
  set(dt, i = r, j = as.character(zero_from:last_col), value = 0)
}

【讨论】:

    【解决方案4】:

    由于您的 dt 中全是 1,您可以通过

    重新创建整个 data.table
    library(data.table)
    
    cols <- ncol(dt)
    data.table(t(sapply(seq_len(nrow(dt)), function(i) 
                       rep(c(1, 0), c(index[i], cols - index[i])))))
    
    
    #     V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11
    # 1:  1  1  1  0  0  0  0  0  0   0   0
    # 2:  1  1  1  1  0  0  0  0  0   0   0
    # 3:  1  1  1  1  1  1  0  0  0   0   0
    # 4:  1  1  1  1  1  1  1  1  1   1   0
    # 5:  1  1  0  0  0  0  0  0  0   0   0
    # 6:  1  1  1  1  1  1  1  1  1   1   0
    # 7:  1  1  1  1  1  1  1  1  1   1   1
    # 8:  1  1  1  1  1  1  1  0  0   0   0
    # 9:  1  1  1  1  1  1  1  0  0   0   0
    #10:  0  0  0  0  0  0  0  0  0   0   0
    #....
    

    将其与前 10 个 index 值进行比较

    index[1:10]
    # [1]  3  4  6 10  2 10 11  7  7  0
    

    【讨论】:

    • 不是反过来(0/1)吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 2021-10-04
    • 2023-02-14
    • 1970-01-01
    • 2020-09-30
    • 2018-05-30
    相关资源
    最近更新 更多