NetworkX - Установка атрибутов узла из фрейма данных - PullRequest
0 голосов
/ 03 февраля 2019

Мне сложно понять, как добавить атрибуты к узлам в моей сети из столбцов в моем фрейме данных.

Ниже приведен пример моего фрейма данных, всего около 10 столбцов, но я использую только 5 столбцов, показанных ниже, при создании моей сети.

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

g = nx.from_pandas_dataframe(df, 'node_from', 'node_to', edge_attr=['attribute1','attribute2','attribute3'])

Сеть будет направленной сетью.Атрибуты, показанные в приведенном ниже кадре данных, являются атрибутами для узлов 'node_from'.Узлы 'node_to' иногда отображаются как узлы 'node_from'.Все узлы, которые могут быть показаны в сети, и их соответствующие атрибуты показаны в таблице df_attributes_only.

df_relationship:

node_from:  node_to: ........ attribute1:   attribute2:   attribute3:
    jim      john    ........    tall          red             fat
    ...

Все столбцы имеют слова в качестве значений, а нецифры.

У меня также есть другой фрейм данных, который имеет каждый возможный узел и их атрибуты:

df_attributes_only:

id:   attribute1:   attribute2:     attribute3:
jim      tall          red             fat
john     small         blue            fat
...

Мне по сути нужно назначить вышеупомянутые три атрибута их соответствующим идентификаторамТаким образом, каждый узел имеет свои 3 атрибута.

Любая помощь в том, как я могу получить атрибуты узла, работающие с моей сетью, очень ценится.

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Это строение ответа @ zohar.kom.Есть способ решить эту проблему без итераций.Этот ответ может быть оптимизирован.Я предполагаю, что атрибуты описывают node_from.

Начните с графика из списка краев (как в anser @ zohar.kom):

 G = nx.from_pandas_edgelist(df, 'node_from', 'node_to')

Вы можете добавить узлыи атрибуты вначале.

 # Create a mask with only the first records
 mask = ~df['node_from'].duplicated()
 # Get a list of nodes with attributes
 nodes = df[mask][['node_from','attribute1','attribute2','attribute3']]

Этот метод добавления узлов из фрейма данных взят из этого ответа .

 # Add the attributes one at a time.
 attr_dict = nodes.set_index('node_from')['attribute1'].to_dict()
 nx.set_node_attributes(G,attr_dict,'attr1')

 attr_dict = nodes.set_index('node_from')['attribute2'].to_dict()
 nx.set_node_attributes(G,attr_dict,'attr2')

 attr_dict = nodes.set_index('node_from')['attribute3'].to_dict()
 nx.set_node_attributes(G,attr_dict,'attr3')

Результат, аналогичный @ zohar.kom, нос меньшими итерациями.

0 голосов
/ 13 февраля 2019

Начиная с Networkx 2.0 , вы можете ввести словарь словарей в nx.set_node_attributes, чтобы установить атрибуты для нескольких узлов.Это гораздо более упорядоченный подход по сравнению с итерацией каждого узла вручную.Внешние ключи словаря представляют каждый узел, а внутренние ключи словаря соответствуют атрибутам, которые вы хотите установить для каждого узла.Примерно так:

attr = {
    node0: {attr0: val00, attr1: val01},
    node1: {attr0: val10, attr1: val11},
    node2: {attr0: val20, attr1: val21},
}

Более подробную информацию вы можете найти в документации .


Используя ваш пример, предполагая, что ваш индекс равен id, выможете преобразовать ваш фрейм данных df_attributes_only атрибутов узла в этот формат и добавить к вашему графику:

df_attributes_only = pd.DataFrame(
    [['jim', 'tall', 'red', 'fat'], ['john', 'small', 'blue', 'fat']],
    columns=['id', 'attribute1', 'attribute2', 'attribute3']
)
node_attr = df_attributes_only.set_index('id').to_dict('index')
nx.set_node_attributes(g, node_attr)

g.nodes['jim']


>>> {'attribute1': 'tall', 'attribute2': 'red', 'attribute3': 'fat'}
0 голосов
/ 03 февраля 2019

nx.from_pandas_dataframefrom_pandas_edgelist в последней стабильной версии 2.2) концептуально преобразует список ребер в граф.Т.е. каждая строка в кадре данных представляет ребро, представляющее собой пару 2 разных узлов .

. С помощью этого API невозможно прочитать атрибуты узлов.Это имеет смысл, поскольку каждая строка имеет два разных узла, и хранение определенных столбцов для разных узлов будет громоздким и может привести к расхождениям.Например, рассмотрим следующий кадр данных:

node_from node_to src_attr_1 tgt_attr_1
  a         b         0         3
  a         c         2         4

Каким должно быть значение 'src_attr_1' для узла a?Это 0 или 2?Более того, нам нужно сохранить два столбца для каждого атрибута (поскольку это атрибут узла, он должен быть у обоих узлов в каждом ребре).По моему мнению, было бы плохим дизайном поддерживать его, и я полагаю, что именно поэтому NetworkX API этого не делает.

Вы все равно можете прочитать атрибуты узлов после преобразования df в график следующим образом:

import networkx as nx
import pandas as pd

# Build a sample dataframe (with 2 edges: 0 -> 1, 0 -> 2, node 0 has attr_1 value of 'a', node 1 has 'b', node 2 has 'c')
d = {'node_from': [0, 0], 'node_to': [1, 2], 'src_attr_1': ['a','a'], 'tgt_attr_1': ['b', 'c']}
df = pd.DataFrame(data=d)
G = nx.from_pandas_edgelist(df, 'node_from', 'node_to')

# Iterate over df rows and set the source and target nodes' attributes for each row:
for index, row in df.iterrows():
    G.nodes[row['node_from']]['attr_1'] = row['src_attr_1']
    G.nodes[row['node_to']]['attr_1'] = row['tgt_attr_1']

print(G.edges())
print(G.nodes(data=True))

Редактировать:

Если вы хотите иметь большой список атрибутов для исходного узла, вы можете автоматически извлечь словарь из этих столбцов следующим образом:

#List of desired source attributes:
src_attributes = ['src_attr_1', 'src_attr_2', 'src_attr_3']

# Iterate over df rows and set source node attributes:
for index, row in df.iterrows():
    src_attr_dict = {k: row.to_dict()[k] for k in src_attributes}    
    G.nodes[row['node_from']].update(src_attr_dict)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...