Построить график NetworkX из Pandas DataFrame

Я хотел бы создать несколько графиков NetworkX из простого Pandas DataFrame:

        Loc 1   Loc 2   Loc 3   Loc 4   Loc 5   Loc 6   Loc 7
Foo     0       0       1       1       0       0           0
Bar     0       0       1       1       0       1           1
Baz     0       0       1       0       0       0           0
Bat     0       0       1       0       0       1           0
Quux    1       0       0       0       0       0           0

Где Foo… - индекс, а Loc 1 - Loc 7 - столбцы. Но преобразование в матрицы или рекурсии Numpy, похоже, не работает для генерации ввода для nx.Graph(). Существует ли стандартная стратегия для достижения этой цели? Я не прочь переформатировать данные в Pandas → dumping в CSV → импортировать в NetworkX, но кажется, что я должен иметь возможность генерировать ребра из индекса и узлов из значений.

Ответ 1

NetworkX ожидает квадратную матрицу (узлов и ребер), возможно, вы хотите передать ее:

In [11]: df2 = pd.concat([df, df.T]).fillna(0)

Примечание. Важно, чтобы индекс и столбцы были в одном порядке!

In [12]: df2 = df2.reindex(df2.columns)

In [13]: df2
Out[13]: 
       Bar  Bat  Baz  Foo  Loc 1  Loc 2  Loc 3  Loc 4  Loc 5  Loc 6  Loc 7  Quux
Bar      0    0    0    0      0      0      1      1      0      1      1     0
Bat      0    0    0    0      0      0      1      0      0      1      0     0
Baz      0    0    0    0      0      0      1      0      0      0      0     0
Foo      0    0    0    0      0      0      1      1      0      0      0     0
Loc 1    0    0    0    0      0      0      0      0      0      0      0     1
Loc 2    0    0    0    0      0      0      0      0      0      0      0     0
Loc 3    1    1    1    1      0      0      0      0      0      0      0     0
Loc 4    1    0    0    1      0      0      0      0      0      0      0     0
Loc 5    0    0    0    0      0      0      0      0      0      0      0     0
Loc 6    1    1    0    0      0      0      0      0      0      0      0     0
Loc 7    1    0    0    0      0      0      0      0      0      0      0     0
Quux     0    0    0    0      1      0      0      0      0      0      0     0

In[14]: graph = nx.from_numpy_matrix(df2.values)

Это не передает имена столбцов/индексов на график, если вы хотите сделать это, вы можете использовать relabel_nodes (возможно, вам придется быть осторожным дубликатов, которые разрешены в pandas 'DataFrames):

In [15]: graph = nx.relabel_nodes(graph, dict(enumerate(df2.columns))) # is there nicer  way than dict . enumerate ?

* Непонятно, что именно представляют столбцы и индекс для желаемого графика.

Ответ 2

Немного поздний ответ, но теперь networkx может читать данные из pandas dataframes, в этом случае в идеале формат выглядит следующим образом: простой ориентированный граф:

+----------+---------+---------+
|   Source |  Target |  Weight |
+==========+=========+=========+
| Node_1   | Node_2  |   0.2   |
+----------+---------+---------+
| Node_2   | Node_1  |   0.6   |   
+----------+---------+---------+

Если вы используете матрицы смежности, то Энди Хейден прав, вы должны позаботиться о правильном формате. Поскольку в вашем вопросе вы использовали 0 и 1, я думаю, вы хотели бы видеть неориентированный граф. Это может показаться противоречивым первым, поскольку вы указали, что индекс представляет собой, например, человек и столбцы представляют группы, к которым принадлежит данное лицо, но это также верно и в том, что группа (членство) принадлежит человеку. Следуя этой логике, вы должны на самом деле поставить группы в индексы и лица в столбцах.

Просто примечание: вы также можете определить эту проблему в смысле ориентированного графа, например, вы хотели бы визуализировать сеть ассоциаций иерархических категорий. Там ассоциация, например, от Samwise Gamgee до Hobbits сильнее, чем в другом направлении (так как Frodo Baggins, скорее всего, прототип Hobbit)