igraph Graph from numpy or pandas adjacency matrix

LondonRob picture LondonRob · Apr 15, 2015 · Viewed 13.3k times · Source

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.

Answer

RickardSjogren picture RickardSjogren · Apr 16, 2015

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