【问题标题】:Update multiple columns by reference in data.table with a single vector通过引用在 data.table 中使用单个向量更新多个列
【发布时间】:2018-07-09 15:42:29
【问题描述】:

我正在尝试使用函数的输出通过引用 data.table 的多个列来更新。作为一个例子,我设置了一个假函数和一个假 dt:

exampleDT <- data.table(1:6, 0,0,0,0,0,0,0,0)
exampleDF <- as.data.frame(exampleDT) 
exampleFUN <- function(x){seq(x, x+7)}

预期输出:

for(i in 1:NROW(exampleDF)){
exampleDF[i, 2:9] <- exampleFUN(i)
}  

  V1 V2 V3 V4 V5 V6 V7 V8 V9
1  1  1  2  3  4  5  6  7  8
2  2  2  3  4  5  6  7  8  9
3  3  3  4  5  6  7  8  9 10
4  4  4  5  6  7  8  9 10 11
5  5  5  6  7  8  9 10 11 12
6  6  6  7  8  9 10 11 12 13

请注意,我的 DT 有一百万行,如果您能指出一个快速的解决方案,我将不胜感激。

EDIT1: 我提供的功能只是一个示例,真正的功能更复杂。它在考虑边界的情况下在栅格中查找相邻像元。第一列包含我想要邻居的单元格 ID。理想情况下,代码应该是这样的:

for(i in 1:NROW(exampleDT)) {
  set(exampleDT, i=i, j=2:9, value=exampleFUN(exampleDT[i, V1]))
}

EDIT2: 我打算使用的实际功能:

neighbourF <- function(CellID, cols, ncell) {

  if(CellID == 1) { # Top right corner
      return(c(NA, NA, NA, CellID + cols , CellID + (cols + 1) , CellID + 1, NA, NA))

  } else if(CellID %in% 2:(cols-1)) { # Top row
      return(c(NA, CellID - 1 , CellID + (cols - 1) , CellID + cols , CellID + (cols + 1) , CellID + 1, NA, NA))

  } else if(CellID == cols) { # Top right corner
      return(c(NA, CellID - 1 , CellID + (cols - 1) , CellID + cols, NA, NA, NA, NA))

  } else if(CellID %in% seq(cols+1, ncell-cols, cols)) { # Left column
      return(c(NA, NA, NA, CellID + cols , CellID + (cols + 1) , CellID + 1 , CellID - (cols - 1) , CellID - cols))

  } else if(CellID == ncell-cols+1) { # Bottom left corner
      return(c(NA, NA, NA, NA, NA, CellID + 1 , CellID - (cols - 1) , CellID - cols))

  } else if(CellID %in% (ncell-cols+2):(ncell-1)) { # Bottom row
      return(c(CellID - (cols + 1) , CellID - 1 , NA, NA, NA, CellID + 1 , CellID - (cols - 1) , CellID - cols))

  } else if(CellID == ncell) { # Bottom right corner
      return(c(CellID - (cols + 1) , CellID - 1 , NA, NA, NA, NA, NA, CellID - cols))  

  } else if(CellID %in% seq(2*cols, ncell-cols, cols)) { # Right column
      return(c(CellID - (cols + 1) , CellID - 1 , CellID + (cols - 1) , CellID + cols , NA, NA, NA, CellID - cols))

  } else {
      return(c(CellID - (cols + 1) , CellID - 1 , CellID + (cols - 1) , CellID + cols , CellID + (cols + 1) , CellID + 1 , CellID - (cols - 1) , CellID - cols))

  }

}

干杯

【问题讨论】:

  • 编写现有函数的矢量化实现相对简单(我看到@Jaap 这样做的时间比我输入此评论的时间要短) ,但我怀疑您的实际用例涉及更复杂的事情。如果 Jaap 在下面的回答不能满足您的需求,您能否就您实际执行的操作提供更多颜色?每行中的值是否递归地依赖于前面的行?
  • @MattSummersgill,我更新了我的问题,更好地描述了我打算使用的功能
  • 谢谢,这可以更好地说明您要完成的工作。对于这种特定情况,我认为使用 R 中的一些矩阵工具可能对您最有用。这个问题的答案是否:Find Neighbouring Elements of a Matrix in R 看起来可能是您解决问题的一个很好的起点? @gregor 在那里提供了一个非常深入的答案。
  • @MattSummersgill 感谢您指出该主题。我写的函数比主题中的函数快 1-2 个数量级(即使有 60M 单元格)。我的问题是脚本的后续部分,我需要处理每个输出以检查哪个邻居与我正在分析的单元格具有最接近的值,检查它是否是互惠的以及它是否是合并的。

标签: r data.table


【解决方案1】:

一个可能的解决方案:

# option 1
exampleDT[, (2:9) := .SD + outer(.I, 0:7, `+`), .SDcols = 2:9][]

# option 2
exampleDT[, (2:9) := .SD + outer(1:nrow(exampleDT), 0:7, `+`), .SDcols = 2:9][]

给出:

> exampleDT
   V1 V2 V3 V4 V5 V6 V7 V8 V9
1:  1  1  2  3  4  5  6  7  8
2:  2  2  3  4  5  6  7  8  9
3:  3  3  4  5  6  7  8  9 10
4:  4  4  5  6  7  8  9 10 11
5:  5  5  6  7  8  9 10 11 12
6:  6  6  7  8  9 10 11 12 13

【讨论】:

  • 嗨,jaap,我在脚本中使用的真正功能非常复杂。我正在编辑我的问题
  • @GeraldT 您能否更新您的问题以更好地反映您正在使用的功能的复杂性?现在它没有了,这让你很难猜测你想要实现什么。
猜你喜欢
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
  • 2021-12-19
  • 2013-05-26
  • 1970-01-01
相关资源
最近更新 更多