【问题标题】:The distances between lists of vertices (not two vertices) in pythonpython中顶点列表(不是两个顶点)之间的距离
【发布时间】:2019-07-29 15:21:41
【问题描述】:

我之前在 igraph 中使用了函数distance(),它计算两个节点或两个节点向量之间的距离。现在我正在使用NetworkX 2.2 在python 中编写代码,并且我还试图找到两个节点列表之间的距离(不是两个节点)

似乎在 NetworkX 中没有功能可以做到这一点。事实上,我使用了shortest_path_length(),但它没有用。我在这里做的是:1.逐条读取图形,2.然后为每条边选择第一个顶点v1和第二个顶点v2,3.找到连接到第一个顶点的邻居并找到连接的邻居到第二个顶点,4.最后计算v1的邻居和v2的邻居之间的距离。

最后我想得到,对于每条边,一个向量包含顶点 v1 和 v2 的邻居之间的距离。我在 R 中的代码

library(igraph)
graph<-matrix(c(4,3,4,1,4,2,3,2,3,1),ncol=2,byrow=TRUE)
g<-graph.data.frame(d = graph, directed = FALSE)

v1<-c()
v2<-c()
n1<-list()
n2<-list()
distance<-list()
distance.bt.neighbors<-list()

for(edge in 1:length(E(g))){
  v1[edge]<-ends(graph = g, es = edge)[1]
  v2[edge]<-ends(graph = g, es = edge)[2]
  n1<-neighbors(g,v1[edge],mode=c("all"))
  n2<-neighbors(g,v2[edge],mode=c("all"))
  distance[[edge]]<-distances(g, v = n1, to = n2, mode = c("all"))
  distance.bt.neighbors[[edge]]<-c(distance[[edge]])
                           }
distance.bt.neighbors
[[1]]
[1] 1 1 1 1 0 2 1 2 0

[[2]]
[1] 1 1 1 0 1 1

[[3]]
[1] 1 1 1 0 1 1

[[4]]
[1] 0 1 1 1 1 1

[[5]]
[1] 0 1 1 1 1 1

为了在python中做到这一点,我写了这段代码

import os
import igraph
import numpy as np
import networkx as nx

os.chdir('Desktop')

graph = nx.read_edgelist("attempt") # the file attempt contains the same data as in the R code.

neighbor1 = []
neighbor2 = []
distance = []

for edge in list(graph.edges):
  neighbor1.append(list(graph.neighbors(edge[0])))
  neighbor2.append(list(graph.neighbors(edge[1])))
  distance.append(nx.shortest_path_length(graph, source=neighbor1, target= neighbor2))

但我收到此错误,指出邻居未定义为顶点,因为它们不是单个值的列表

Traceback (most recent call last):
File "<stdin>", line 4, in <module>
File "/home/abdelrahman/anaconda/lib/python3.7/site-packages/networkx/algorithms/shortest_paths/generic.py", line 312, in shortest_path_length
p = nx.bidirectional_shortest_path(G, source, target)
File "/home/abdelrahman/anaconda/lib/python3.7/site-packages/networkx/algorithms/shortest_paths/unweighted.py", line 223, in bidirectional_shortest_path
raise nx.NodeNotFound(msg.format(source, target))
networkx.exception.NodeNotFound: Either source [['3', '4']] or target [['1', '2']] is not in G

在 python 中是否有可能获得一个顶点列表之间的距离列表,而不是像我在 R 中所做的那样的单个值?有没有这样的功能,如果没有,是否可以修改当前的功能?

注意:我没有使用 igraph-python 来获取所需的列表,原因有两个:根据我的搜索,在 igraph 中没有这样的功能,以及避免丢失 tryinh 时产生的顶点名称的问题获取顶点的邻居。

【问题讨论】:

    标签: python networkx igraph


    【解决方案1】:

    给出错误的代码的最后一行。 在Forneighbor1neighbor2 内部在每次迭代后更新为具有多个节点的列表,对于nx.shortest_path_length,您需要传递单个源和单个目标节点,而不是列表。 我希望这会有所帮助。

    更新

    这是解决您的问题的示例代码。 graph.neighbors(node) 将给出该节点的邻居列表。

     import networkx as nx
    import pandas as pd
    G = nx.path_graph(5)
    Distance=[]
    edge0=[]
    neighbor0edge0=[]
    neighbor1edge1=[]
    edge1=[]
    Output=pd.DataFrame()
    for edge in G.edges():
        neighbor1=[n for n in G.neighbors(edge[0])] #neighborrs w.r.t v1
        neighbor2=[n for n in G.neighbors(edge[1])] #neighborrs w.r.t v2
        distance=[]
        for i in neighbor1:
            for j in neighbor2:
                  distance.append(nx.shortest_path_length(G, source=i, target=j)) #Find distance between all the combination of neighbor1 and neighbor2
        edge0.append(edge[0])
        edge1.append(edge[1])
        Distance.append(distance)
        neighbor0edge0.append(neighbor1)
        neighbor1edge1.append(neighbor2)
    Output['v1']=edge0
    Output['neighborv1']=neighbor0edge0
    Output['v2']=edge1
    Output['neighborv2']=neighbor1edge1
    Output['Distances']=Distance
    

    结果:-

    `v1 neighborv1  v2 neighborv2     Distances
     0        [1]   1     [0, 2]        [1, 1]
     1     [0, 2]   2     [1, 3]  [1, 3, 1, 1]
     2     [1, 3]   3     [2, 4]  [1, 3, 1, 1]
     3     [2, 4]   4        [3]        [1, 1]`
    

    【讨论】:

    • 我现在收到你的问题了。您想遍历所有边并找到连接到边的节点之间的距离。你还需要邻居的名字还是距离?我会更新我的答案。
    • 我知道这是原因,我在问题标题中指出如何获取列表之间的距离而不是单个节点!
    • 一点也不!不是节点之间的距离位于边上。我需要遍历所有边然后对于每条边我要执行以下操作:每条边上有两个顶点 v1 和 v2,在图中找到 v1 的邻居并将它们存储在数组邻居 1 中,还找到图中v2的邻居并将它们存储在数组neighbors2中。最后计算两个数组中邻居之间的距离,因此结果是一个数组列表,表示邻居1和邻居2之间的距离
    【解决方案2】:

    你已经很接近了,除了在最后一个循环中你必须再次遍历邻居列表然后存储距离

    import numpy as np
    import networkx as nx
    
    # Since I didn't have your data, I simply recreated from your R code
    graph = nx.Graph()
    for i in range(1, 5):
      graph.add_node(i)
    
    for x,y in [(4, 3), (4, 1), (4, 2), (3, 2), (3, 1)]:
      graph.add_edge(x, y)
    
    # print(graph.edges())
    # Output EdgeView([(4, 3), (4, 1), (4, 2), (3, 2), (3, 1)])
    
    distance_neighbors = {}
    
    for edge in list(graph.edges):
      neighbor1 = tuple(graph.neighbors(edge[0]))
      neighbor2 = tuple(graph.neighbors(edge[1]))
    
      distance_list = []
      for v1 in neighbor1:
        for v2 in neighbor2:
          distance_list.append(nx.shortest_path_length(graph, source=v1, target=v2))
      distance_neighbors[edge] = distance_list
    

    distance_neighbours 包含以下数据:

    {(1, 3): [0, 1, 1, 1, 1, 1],
     (1, 4): [1, 1, 1, 0, 1, 1],
     (2, 3): [0, 1, 1, 1, 1, 1],
     (2, 4): [1, 1, 1, 0, 1, 1],
     (3, 4): [1, 1, 1, 1, 2, 0, 1, 0, 2]}
    

    最后一条边 (3,4) 中值的排序不同,因为 Python 对邻居的排序与 R 的不同。 为了确保行为相同,请运行以下代码:

    import os
    
    import numpy as np
    import networkx as nx
    
    # Since I didn't have your data, I simply recreated from your R code
    graph = nx.Graph()
    for i in range(1, 5):
      graph.add_node(i)
    
    for x,y in [(4, 3), (4, 1), (4, 2), (3, 2), (3, 1)]:
      graph.add_edge(x, y)
    
    # print(graph.edges())
    # Output EdgeView([(4, 3), (4, 1), (4, 2), (3, 2), (3, 1)])
    
    distance_neighbors = {}
    
    for edge in list(graph.edges):
      # Just sort the neighbours list in reverse order
      neighbor1 = tuple(sorted(graph.neighbors(edge[0]), reverse=True))
      neighbor2 = tuple(sorted(graph.neighbors(edge[1]), reverse=True))
    
      distance_list = []
      for v1 in neighbor1:
        for v2 in neighbor2:
          distance_list.append(nx.shortest_path_length(graph, source=v1, target=v2))
      distance_neighbors[edge] = distance_list
    

    现在distance_neighbors 的输出与您的 R 代码相同:

    {(1, 3): [0, 1, 1, 1, 1, 1],
     (1, 4): [1, 1, 1, 0, 1, 1],
     (2, 3): [0, 1, 1, 1, 1, 1],
     (2, 4): [1, 1, 1, 0, 1, 1],
     (3, 4): [1, 1, 1, 1, 0, 2, 1, 2, 0]}
    

    这是上面代码的link to the Google Colab notebook

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-31
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      • 1970-01-01
      相关资源
      最近更新 更多