igraph Graph from numpy or pandas adjacency matrix

北城以北 提交于 2019-11-28 21:16:14

问题


I have an adjacency matrix stored as a pandas.DataFrame:

node_names = ['A', 'B', 'C']
a = pd.DataFrame([[1,2,3],[3,1,1],[4,0,2]],
    index=node_names, columns=node_names)
a_numpy = a.as_matrix()

I'd like to create an igraph.Graph from either the pandas or the numpy adjacency matrices. In an ideal world the nodes would be named as expected.

Is this possible? The tutorial seems to be silent on the issue.


回答1:


In igraph you can use igraph.Graph.Adjacency to create a graph from an adjacency matrix without having to use zip. There are some things to be aware of when a weighted adjacency matrix is used and stored in a np.array or pd.DataFrame.

  • igraph.Graph.Adjacency can't take an np.array as argument, but that is easily solved using tolist.

  • Integers in adjacency-matrix are interpreted as number of edges between nodes rather than weights, solved by using adjacency as boolean.

An example of how to do it:

import igraph
import pandas as pd

node_names = ['A', 'B', 'C']
a = pd.DataFrame([[1,2,3],[3,1,1],[4,0,2]], index=node_names, columns=node_names)

# Get the values as np.array, it's more convenenient.
A = a.values

# Create graph, A.astype(bool).tolist() or (A / A).tolist() can also be used.
g = igraph.Graph.Adjacency((A > 0).tolist())

# Add edge weights and node labels.
g.es['weight'] = A[A.nonzero()]
g.vs['label'] = node_names  # or a.index/a.columns

You can reconstruct your adjacency dataframe using get_adjacency by:

df_from_g = pd.DataFrame(g.get_adjacency(attribute='weight').data,
                         columns=g.vs['label'], index=g.vs['label'])
(df_from_g == a).all().all()  # --> True



回答2:


Strictly speaking, an adjacency matrix is boolean, with 1 indicating the presence of a connection and 0 indicating the absence. Since many of the values in your a_numpy matrix are > 1, I will assume that they correspond to edge weights in your graph.

import igraph

# get the row, col indices of the non-zero elements in your adjacency matrix
conn_indices = np.where(a_numpy)

# get the weights corresponding to these indices
weights = a_numpy[conn_indices]

# a sequence of (i, j) tuples, each corresponding to an edge from i -> j
edges = zip(*conn_indices)

# initialize the graph from the edge sequence
G = igraph.Graph(edges=edges, directed=True)

# assign node names and weights to be attributes of the vertices and edges
# respectively
G.vs['label'] = node_names
G.es['weight'] = weights

# I will also assign the weights to the 'width' attribute of the edges. this
# means that igraph.plot will set the line thicknesses according to the edge
# weights
G.es['width'] = weights

# plot the graph, just for fun
igraph.plot(G, layout="rt", labels=True, margin=80)



来源:https://stackoverflow.com/questions/29655111/igraph-graph-from-numpy-or-pandas-adjacency-matrix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!