Цвет и веса в сети

#python #networkx

#python #networkx

Вопрос:

Я хотел бы создать график, в котором узлы имеют разный вес и цвет на основе значений в столбцах.

Образец данных

Узел Вес Цвет Соседи
1 23 красный [3,5]
3 18 Синий [2]
4 50 Синий []
5 18 Синий [1]
2 36 Зеленый [3]

В таблице выше показаны ссылки по узлам:

  • узел 1 связан с 3 и 5. Он имеет вес 23 и красный цвет
  • узел 2 связан с 3. Он имеет вес 36 и зеленый цвет
  • узел 3 связан с 2. Он имеет вес 18 и синий цвет
  • узел 4 не имеет ссылок. Он имеет синий цвет и вес 50
  • узел 5 связан с 1. Он имеет вес 18 и синий цвет

Для построения сети я сделал следующее

 d = dict(df.drop_duplicates(subset=['Node','Colour'])[['Node','Colour']].to_numpy().tolist())

nodes = G.nodes()
plt.figure(figsize=(30,30)) 
pos = nx.draw(G, with_labels=True, 
              nodelist=nodes,
              node_color=[d.get(i,'lightgreen') for i in nodes], 
              node_size=1000) 
 

К сожалению, все цвета неверны! Кроме того, у меня возникают трудности с добавлением информации о весах.
Связи между узлами должны иметь присвоенные им веса.
Я пробовал с edge_attr='weight' помощью in nx.draw , где 'weight' = df['Weight'] .
Я надеюсь, что вы можете оказать мне некоторую помощь и сообщить, что я сделал не так.

Ответ №1:

 node_color=[d.get(i,'lightgreen') for i in nodes], 
 

Этот метод раскраски не сработал, потому что вы назначаете цвета в соответствии с nodes вместо их цветов.

«Связи между узлами должны иметь присвоенные им веса. Я пробовал использовать edge_attr=’weight’ в nx.draw, где ‘weight’ = df[‘Вес’].»*

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

Узел Вес Цвет Соседи Edge_Weights
1 23 красный [3,5] [w1_3,w1_5]
3 18 Синий [2] [w3_2]
4 50 Синий [] []
5 18 Синий [1] [w5_1]
2 36 Зеленый [3] [w2_3]

Затем добавьте вес ребра, используя G.add_edge(n1,n2,wight=w) , вот некоторая документация.

Поскольку у вас есть несколько атрибутов, которые вы хотите добавить к своим узлам, я бы рекомендовал выполнить итерацию по вашему фрейму данных, используя, например df.itertuples() .

Вот полный код:

 df = pd.DataFrame(  data = {'Node': [1, 3, 4, 5, 2], 
                        'Weight': [23, 18 ,50, 18, 36], 
                        'Colour': ["red", "blue", "blue", "blue", "green"], 
                        'Neighbors': [[3,5], [2], [], [1], [3]]
                        }
              )
   

NROWS = None
def get_graph_from_pandas(df:
    
    G = nx.DiGraph() # assuming the graph is directed since e.g node 1 has 
                     # 3 as neighbour but 3 doesnt have 1 as neighbour
    
    
    for row in df.itertuples(): # row is the row of the dataframe
        n = row.Node   # change to row.(name of column with the node names)
        w = row.Weight # change to row.(name of column with the node weights)
        c = row.Colour # change to row.(name of column with the node colors)
        neighbors = row.Neighbors
        
        G.add_node(n, weight = w, colour = c)
        
        for neigh in neighbors:
            #add edge weights here, attribute of G.add_edge
            G.add_edge(n,neigh)  
            
    return G
        
        
        
G = get_graph_from_pandas(df)

print("Done.")
print("Total number of nodes: ", G.number_of_nodes())
print("Total number of edges: ", G.number_of_edges())

pos = nx.draw(G, with_labels=True, 
              node_color=[node[1]['colour'] for node in G.nodes(data=True)], 
              node_size=200)
 

Комментарии:

1. Привет, willcrack, спасибо за ваш ответ. Не могли бы вы, пожалуйста, объяснить мне эту строку кода: node_color=[node[1]['colour'] for node in G.nodes(data=True)] я получаю сообщение об ошибке: KeyError: 'colour' когда я расширяю график на весь набор данных. Большое спасибо

2. Привет! Пока вы делаете: c = row.Colour , G.add_node(n, weight = w, colour = c) он не должен возвращать эту ошибку

3. node_color=[node[1]['colour'] for node in G.nodes(data=True)] Эта строка использует понимание списка , чтобы вернуть список с цветом ваших узлов.

4. Я считаю, что создание нового сообщения — лучший вариант

5. Np @Val 😉 рад, что смог помочь