我以前在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产生的顶点名称丢失的问题。为顶点求邻居。
答案 0 :(得分:1)
您很亲密,除了在最后一个循环中,您必须再次遍历邻居列表然后存储距离
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。
希望这会有所帮助!
答案 1 :(得分:0)
代码的最后一行给出了错误。
在For
neighbor1
和neighbor2
内部,每次迭代后都更新为具有多个节点的列表,对于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]`