【问题标题】:Optimize node-matching objective with unique node using data.table使用 data.table 优化具有唯一节点的节点匹配目标
【发布时间】:2015-12-16 20:35:25
【问题描述】:

我有 2 组由 id1 和 id2 表示的节点。 我有一个数据表,其中包含对节点的惩罚——键(id1,id2),值是惩罚。

我如何有效地将 data.table 划分为具有最小惩罚的节点对,以使每个节点(id1 和 id2)出现一次?

简单示例:

输入数据表:

dtIn <- data.table(
    id1 = rep(letters[1:3], each=3)
  , id2 = rep(1:3, 3)
  , penalty = 1:9
)
setkey(dtIn, id1, id2)

print(dtIn)
   id1 id2 penalty
1:   a   1       1
2:   a   2       2
3:   a   3       3
4:   b   1       4
5:   b   2       5
6:   b   3       6
7:   c   1       7
8:   c   2       8
9:   c   3       9

所需的输出数据表:

   id1 id2 penalty
1:   a   1       1
2:   b   2       5
3:   c   3       9

我知道如何实现编写循环的算法:按惩罚排序,遍历记录,如果之前没有节点匹配,则按顺序挑选每一对。请参阅下面的代码。

当然,对于我的真实大小的数据,这样的循环运行速度慢得令人难以忍受。

逻辑上正确但性能太差的手动循环功能:

manualIter <- function(dtIn) {
  setkey(dtIn, penalty, id1, id2) # Enusred ordered by penalty.
  id1Match <- NULL; id2Match <- NULL; pen <- NULL;
  for (i in seq_len(nrow(dtIn))) {
    if (!(dtIn$id1[i] %in% id1Match) && !(dtIn$id2[i] %in% id2Match)) {
      id1Match <- c(id1Match, dtIn$id1[i])
      id2Match <- c(id2Match, dtIn$id2[i])
      pen <- c(pen, dtIn$penalty[i])
    }
  }
  # Build the return data.table for the matching ids.
  dtf <- data.table(id1 = id1Match, id2 = id2Match, penalty = pen)
  setkey(dtf, id1, id2)
  return(dtf)
}

那么问题是如何有效地向量化这个算法呢?

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    更新了答案。我不确定您是否可以将其矢量化。我认为这本质上是一个递归问题。我的回答很简单(根据惩罚对数据进行排序):

    dtOut <- list()
    dtOut[[1]] <- dtIn[1]
    i <- 2
    while(dtIn[, .N] > 0) {
      dtIn <- dtIn[!(id1 == dtOut[[i - 1]][, id1] | id2 == dtOut[[i - 1]][, id2])]
      if(dtIn[, .N] < 1) break
      dtOut[[i]] <- dtIn[1]
      i <- i + 1
    }
    dtOut <- rbindlist(dtOut)
    

    【讨论】:

    • 谢谢@danas.zuokas。你的代码比我的略短,但在我非常小的测试集上,它的执行速度慢了大约 1 个数量级。
    • 可能是rbind 会减慢速度。我会更新答案。
    • 谢谢@danas.zuokas。这个版本比以前的版本稍微快一点,但仍然远远落后于我提出的循环。看起来没有明显的方法可以在 R 中有效地实现这个逻辑!求助于处理快速显式循环的 Julia!
    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 2015-04-30
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 2018-08-20
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多