我有一个 igraph
具有 103,887 个节点和 4,795,466 个关系的网络图。
这可以构造为 data.table
中的边列表有近 900 万行。
我可以按照@chinsoon12 的回答here 在这个网络中找到共同的邻居.请参阅下面的示例。
这对于较小的网络非常有效,但在我的用例中遇到了问题,因为 合并结果超过 2^31 行 .
问题:
示例 - 从@chinsoon12 的回答修改:
library(data.table)
library(igraph)
set.seed(1234)
g <- random.graph.game(10, p=0.10)
adjSM <- as(get.adjacency(g), "dgTMatrix")
adjDT <- data.table(V1=adjSM@i+1, V2=adjSM@j+1)
res <- adjDT[adjDT, nomatch=0, on="V2", allow.cartesian=TRUE
][V1 < i.V1, .(Neighbours=paste(V2, collapse=",")),
by=c("V1","i.V1")][order(V1)]
res
V1 i.V1 Neighbours
1: 4 5 8
2: 4 10 8
3: 5 10 8
最佳答案
common neighbors
Can I split the data and do the computation in steps?
您可以按 V1 拆分以避免遇到大合并问题:
neighDT = adjDT[, if (.N > 1) {
cb = combn(V2, 2)
.(a = cb[1, ], b = cb[2, ])
}, by=.(neighbor = V1)]
这使 neighbor a b
1: 8 4 5
2: 8 4 10
3: 8 5 10
(OP 发现 gRbase::combnPrim
比这里的 combn
快。)How can we collapse all the common neighbors (separated with a comma) for the same combination into one observation?
neighDT_agg = neighDT[order(neighbor),
.(neighbors = toString(neighbor))
, keyby=.(a,b)]
order
确保字符串按字母顺序排序。 keyby
确保表按对 {a,b} 排序,并有助于一次对多个对进行简单的快速查找:# single query
neighDT_agg[.(4,10), neighbors]
# [1] "8"
# multi query
pairs_queryDT = data.table(a = c(4,5,8), b = c(5,10,10))
neighDT_agg[pairs_queryDT, neighbors]
[1] "8" "8" NA
I have an igraph network graph with 103,887 nodes and 4,795,466 ties.
每次调用
combn
将制作一个 2-by- choose(.N, 2)
矩阵。如果一个节点连接到所有其他节点,那么它是所有其他节点对的共同邻居,您将面临 choose(103887-1, 2)
这些对。我想这更像是定义问题的方式而不是解决问题的方法的问题。The results will be used to query about common neighbors.
对于上述方法,您需要先计算完整的邻居表。
如果您只有一些关于相交邻居的临时查询:
find_neighbors <- function(a, b){
adjDT[.(c(a, b)), on=.(V1), V2[duplicated(V2)]]
}
find_neighbors(4, 10)
# [1] 8
这可以类似地包装在 toString
中折叠值。
关于R - 使用 data.table 连接超过 2^31 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69422341/