R:网络分析——操纵邻接矩阵得到"common links"矩阵



我正在使用IGRAPH R软件包进行一些网络分析。

我必须操纵定向的,加权的邻接矩阵(从 igraph 对象中提取具有函数_as_Adjacency_matrix(...(_的对象,以获得不同考虑到两个节点彼此共享的 incoming 的矩阵。

假设4节点:节点 a 连接到节点 c ,节点 b 连接到 a a ,节点 c 连接到节点 a b ,连接到 a 的节点 d 所有要定向的链接。

在此设置中, a b 共享来自 c 的内向链接,但没有其他节点共享任何传入链接。

因此,我想创建一个能够创建定向加权邻接列表的例程节点I,J相互共享。

结果必须是一个对称的逻辑矩阵(仅是true/false值(,在结果的"公共链接"邻接矩阵的前面,而不是定向。

回到我做的示例,只有条目[ a b ]和[ b a 应具有非零值,等于来自共享连接节点的内向边缘的值([ a b ]应包含[ c c -> a ]值,而[ b a ]应该包含[ c -> b ]值(。

关于它的任何建议将不胜感激

有趣但略有定义的问题。我很难理解您所需的输出,但我想我明白了。我在下面的第一次尝试中留下了代码。您提供的示例数据我称为g

无论哪种方式,我都认为您可以从这个代码示例中进行很多工作。我非常开放以一种更聪明的方法来无需循环以换取速度,但这是我可能想出的最教学代码,因为我不确定所需的输出。

如果我正确理解了您的问题,您所要求的内容将在列表UL中输出,其中ul[[x]][[3]]包含一个图的e((,其中边缘从节点i( ul[[x]][[1]](转到i和i and i和i的每个节点J共享传入链接在图g中。

library(igraph)
# Assume 4 nodes:
# - node A is connected to node C,
# - node B is connected to A,
# - node C is connected to node A and B,
# - node D connected to A
m <- matrix(ncol=4,c(0,0,1,0,
            1,0,0,0,
            1,1,0,0,
            1,0,0,0), byrow=T)
colnames(m) <- rownames(m) <-  c("A","B","C","D")
# Uncomment this stuff to use random network instead
# g <- erdos.renyi.game(n=12, 16, type="gnm", directed=TRUE, loops=FALSE)
# m <- as.matrix(as_adjacency_matrix(g))
# Check that the data is ok
graph_from_adjacency_matrix(m, mode="directed")
g <- graph_from_adjacency_matrix(m, mode="directed")
# Directed weighted adjacency list from the original one, where
# each entry [i,j] represents the sum of the value of incoming
# edge that node i,j share with each other.

# I first missunderstood your question and wrote this output
# This output will be an edgelist containing node-pairs i and j and
# the strength related to the number of other nodes whith which they
# share incoming links.
el <- matrix(ncol=3, nrow=0)
colnames(el) <- c("i","j","strength")
# I then reread your question and made this output containing a list
# wehre every node-pair which share incoming links from the same nodes
# contain the E()-object of igraph-edges from i to each of the nodes
# from which both i and j recieve incoming links in the graph g.
ul <- list()
# Use the empty graph like g to build edgelists
temp.g <- g %>% delete_edges(E(g)) # an empty graph
for(i in V(g)){
    for(j in V(g)){
        # Each node pair is i j for every node in g
        if(i == j){next}

        # Neighborhod() lists linked nodes, in this case at the distance
        # of exactly 1 (mindist and order) for node x using the "in"-coming
        # links:
        in.to.i <- neighborhood(g, order=1, nodes=i, mode="in", mindist=1)
        in.to.j <- neighborhood(g, order=1, nodes=j, mode="in", mindist=1)
        # These are the nodes which all link to both i and j
        shared.incoming <- intersect(in.to.i[[1]], in.to.j[[1]])
        # Make a new graph (gg) with links from each node FROM which i and j both
        # share incoming ties in g TO  i.
        # In the edgelist ul, each row can be read like:
        # In graph g, "i" has "edges" incoming ties in common with "j"
        gg <- temp.g %>% add_edges(unlist(lapply(shared.incoming, function(x) c(x,i)) ))
        # E(gg) is what you want. Add it to the output-list
        ul[[length(ul)+1]] <- list(i, j, as_edgelist(gg, names=T))
        # how many nodes link to both i and j?
        el <- rbind(el,c("i"=i, "j"=j, "edges"=length(shared.incoming) ) )
    }
}
# The whole list of el contains all possible pairs
el
# Strip entries in the edgelist where a pair of nodes don't share any
# in-linking nodes at all
el <- el[el[,'strength'] != 0,  ]
# Since nodes that share in-linking nodes are ALWAYS structually equivilent
# in that they both share in-links from the same other nodes, there is never
# any idea to have this edge-list directed.
# Make the edge-list one-directed by deleting duplicate pairs
el <- el[el[,'i'] < el[,'j'],  ]
# In graph g, these node-pairs share the number of [strength] incoming links
# from the same other nodes.
(el)

# The whole list of ul contains all possible pairs
ul
# You only wanted the pairs which actually contained any shared incoming nodes
keep.from.ul <- unlist(lapply(ul, function(x) ifelse( nrow(x[[3]]) > 0, TRUE, FALSE) ))
ul <- ul[keep.from.ul]

最新更新