前言
记录一下类型转换
1. 从edgelist创建adjacent matrix
1.1 错误方案 networkx
import networkx as nx
edgelist = [(0, 4),
(0, 6),
(0, 8),
(6, 5),
(1, 2),
(1, 3)]
adj = nx.adjacency_matrix(nx.from_edgelist(lis)).toarray()
print(adj)
array([[0, 1, 1, 1, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 1, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0]])
是不是明显感觉不对。
0跟1之间明明没有边才对。
因为networkx会把传进来的node_name根据传入顺序重新编号索引
。
我们传入的第一条边是(0,4),结点0被编号为0,结点4被编号为1。
于是adj里就有了(0,1)相连。
问题是,我们原来存储的edge_list已经编号过了,不劳您费心重新编号啊。
此时需要更lazy的方法。
1.2 正确方案 scipy.sparse.coo_matrix
import scipy
edgelist = np.array([(0, 4),
(0, 6),
(0, 8),
(6, 5),
(1, 2),
(1, 3)]
)
num_edges = len(edgelist)
num_nodes = 9
adj = scipy.sparse.coo_matrix(
(np.ones(num_edges), (edgelist[:, 0], edgelist[:, 1])),
shape=(num_nodes ,num_nodes),
dtype=np.float32)
adj =adj.toarray()
print(adj)
array([[0., 0., 0., 0., 1., 0., 1., 0., 1.],
[0., 0., 1., 1., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)
上面这个方案没有过滤原始数据里可能存在的重复边。
如果需要考虑去重只需要加一句
rows, cols, data = zip(*set(zip(rows, cols, data)))
完整如下
import scipy
import numpy as np
edgelist = np.array([(0, 4),
(0, 6),
(0, 8),
(6, 5),
(1, 2),
(1, 3)]
)
def form_adj(edgelist, num_nodes):
num_edges = len(edgelist)
rows = edgelist[:, 0]
cols = edgelist[:, 1]
data = np.ones(num_edges)
# 去重
rows, cols, data = zip(*set(zip(rows, cols, data)))
adj = scipy.sparse.coo_matrix(
(data, (rows, cols)),
shape=(num_nodes ,num_nodes),
dtype=np.float32)
return adj
adj = form_adj(edgelist, num_nodes = 9)
print(adj.toarray())
1.3 使用外部工具包
事实上edge_list是大部分开源库都支持的一种标准输入格式。
比如 torch_geometric创建图是
edgelist = np.array([(0, 4),
(0, 6),
(0, 8),
(6, 5),
(1, 2),
(1, 3)]
)
edge_index = edgelist.T #(e, |E|)
g = Data(edge_index=edge_index)
dgl同理也把edge_index = (2,|E|) 作为标准输入
2. 从neighbor list 邻接表 创建adjacent matrix
输入形如
[[1],
[0, 2],
[1, 3],
[2, 3]]
这种叫邻接表。
一种简单的想法是把 neighbor list 变成 edge_list 再由第一部分中介绍的 edege list 直接建图。
neigh_list = [[1],
[0, 2],
[1, 3],
[2, 3]]
def neighList_to_edgeList(neigh_list):
edge_list = []
for i in range(len(neigh_list)):
for j in neigh_list[i]:
edge_list.append((int(i),int(j)))
edge_list = np.array(edge_list)
return edge_list