2015-04-15 9 views
16

Ich habe eine Adjazenzmatrix als pandas.DataFrame gespeichert:IGRAPH Graph von numpy oder Pandas Adjazenzmatrix

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() 

Ich mag würde ein igraph.Graph entweder von den pandas oder die numpy Adjazenzmatrizen erstellen. In einer idealen Welt würden die Knoten wie erwartet benannt werden.

Ist das möglich? The tutorial scheint zu dem Thema zu schweigen.

+0

Streng genommen [Adjazenzmatrizen] (http: // en.wikipedia.org/wiki/Adjacency_matrix) sind boolesch. Was bedeuten die Werte in 'a_numpy' eigentlich? Sind sie Verbindungsgewichte? –

+0

@ali_m Ich meinte damit Kantengewichte. – LondonRob

Antwort

20

In IGRAPH können Sie igraph.Graph.Adjacency verwenden, um eine Grafik aus einer Adjazenzmatrix zu erstellen, ohne zip zu verwenden. Es gibt einige Dinge, die beachtet werden müssen, wenn eine gewichtete Adjazenzmatrix verwendet und in einem np.array oder pd.DataFrame gespeichert wird.

  • igraph.Graph.Adjacency kann ein np.array als Argument nicht nehmen, aber das leicht gelöst mit tolist.

  • Ganzzahlen in der Adjazenzmatrix werden als Anzahl der Kanten zwischen den Knoten und nicht als Gewichte interpretiert, die durch Verwendung von Adjazenz als Booleschen Wert gelöst werden.

Ein Beispiel, wie es zu tun:

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 

Sie können Ihre adjacency Datenrahmen rekonstruieren mit get_adjacency von:

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 
+1

Perfekt! +1 für die Tatsache, dass "Adjazenz" Zahlen als eine Anzahl von Links interpretiert, nicht das Linkgewicht. – LondonRob

+0

Wie würden Sie dieses Diagramm in eine gerichtete Version umwandeln, wenn die Zeilen die Von-Knoten und die Spalten die Bis-Knoten wären. –

11

Genau genommen ist ein adjacency matrix boolesch, wobei 1 das Vorhandensein einer Verbindung und 0 die Abwesenheit anzeigt. Da viele der Werte in Ihrer a_numpy Matrix> 1 sind, gehe ich davon aus, dass sie den Kantengewichten in Ihrem Diagramm entsprechen.

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) 

enter image description here

Verwandte Themen