2015-04-15 19 views
16

mam matrycy przylegania przechowywana jako pandas.DataFrame:igraph wykres z numpy lub pandy przylegania matrycy

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

ja ma zostać utworzony igraph.Graph z każdej z pandas lub numpy macierzy przylegania. W idealnym świecie węzły będą nazywane zgodnie z oczekiwaniami.

Czy to możliwe? The tutorial wydaje się milczeć w tej sprawie.

+0

Ściśle mówiąc, [macierze sąsiedztwa] (http: // en.wikipedia.org/wiki/Adjacency_matrix) są boolean. Co właściwie oznaczają wartości w 'a_numpy'? Czy są to wagi połączeń? –

+0

@ali_m Miałem na myśli, że mają na myśli wagę krawędzi. – LondonRob

Odpowiedz

20

W igraph igraph.Graph.Adjacency można użyć do utworzenia wykresu z matrycy przylegania bez konieczności stosowania zip. Jest kilka rzeczy, o których należy pamiętać, gdy macierz ważonej przylegania jest używana i przechowywana w postaci np.array lub.

  • igraph.Graph.Adjacency nie może zabierać np.array jako argument, ale to można łatwo rozwiązać za pomocą tolist.

  • Liczby całkowite w matrycy przyległości są interpretowane jako liczba krawędzi między węzłami, a nie wagami, rozwiązanymi przy użyciu dopasowania jako wartości logicznej.

Przykład jak to zrobić:

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 

można zrekonstruować swoją dataframe adjacency korzystając get_adjacency przez:

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

Idealnie! +1 za fakt, że "Przyleganie" interpretuje liczby jako liczbę linków, a nie wagę linku. – LondonRob

+0

Jak przekonwertowałbyś ten wykres na wersję skierowaną, jeśli wiersze były węzłami "z" a kolumny były węzłami "do". –

11

Ściśle mówiąc, adjacency matrix jest wartością logiczną, przy czym 1 oznacza obecność połączenia, a 0 wskazuje nieobecność. Ponieważ wiele wartości w macierzy a_numpy ma wartość> 1, przyjmę, że odpowiadają one obciążeniom krawędzi na wykresie.

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