为节点分配多个属性 [英] Assigning multiple attributes to nodes

查看:46
本文介绍了为节点分配多个属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为我的节点分配一个属性.目前我正在使用以下数据示例创建网络:

属性源目标权重标签87.5 海森堡泡利 66.3 112.5 贝克汉姆 梅西 38.1 012.5 贝克汉姆马拉多纳 12 043.5 西瓜 33.6 1

标签应该给出节点的颜色(1=黄色,0=蓝色).

网络代码:

 G = nx.from_pandas_edgelist(df, source='Source', target='Target', edge_attr='Weight')collist = df.drop('Weight', axis=1).melt('Label').dropna() # 我需要这个用于下面的代码行,因为我想绘制节点 - 它们的大小 - 基于它们的度数度数=[]对于 collist['value'] 中的 x:度=G.度[x]度数.附加(100*度)pos=nx.spring_layout(G)nx.draw_networkx_labels(G, pos, font_size=10)nx.draw_networkx_nodes(G, pos, nodelist=collist['value'], node_size = degree, node_color=collist['Label'])nx.draw_networkx_edges(G, pos)

这段代码应该做的是:节点的大小应该等于它们的度数(这解释了我的代码中的度数和 collist).边缘的厚度应等于 Weight.Attribute 应该在这个链接中分配(和更新):(

解决方案

import networkx as nx将熊猫导入为 pd导入 matplotlib.pyplot 作为 pltdf = pd.DataFrame({Attribute": [87.5, 12.5, 12.5, 43.5], Source": [Heisenberg", Beckham", Messi", water"], ";目标":[泡利"、梅西"、马拉多纳"、甜瓜"]、体重":[66.3、38.1、12、33.6]、标签":[1、0, 0,1]})G = nx.from_pandas_edgelist(df, source='Source', target='Target', edge_attr='Weight')source_attrs = {df.Source[i]: {Attribute": df.Attribute[i]} for i in range(len(df.Attribute))}target_attrs = {df.Target[i]: {Attribute": df.Attribute[i]} for i in range(len(df.Attribute))}nx.set_node_attributes(G, source_attrs)nx.set_node_attributes(G, target_attrs)degree=[100*G.degree[i] for i in G.nodes()]weights = [G[u][v]['Weight']/10 for u,v in G.edges()]颜色 = []对于 G.nodes() 中的节点:如果 source_attrs.keys() 中的节点:color.append('黄色')别的:color.append('蓝色')pos=nx.spring_layout(G)pos_attrs = {}对于节点,pos.items() 中的坐标:pos_attrs[node] = (coords[0], coords[1] + 0.08)标签 = nx.get_node_attributes(G,属性")custom_node_attrs = {}对于节点,labels.items() 中的属性:custom_node_attrs[node] = str(node) + str(attr)nx.draw_networkx_labels(G,pos_attrs,labels=custom_node_attrs,font_size=10)nx.draw_networkx_nodes(G, pos, nodelist=G.nodes(), node_size = degree, node_color=colors)nx.draw_networkx_edges(G,pos, width=weights)plt.show()

I would like to assign to my nodes an attribute. Currently I am creating a network using the following sample of data:

Attribute   Source       Target Weight  Label
    87.5    Heisenberg   Pauli  66.3    1
    12.5    Beckham      Messi  38.1    0
    12.5    Beckham      Maradona 12    0
    43.5    water        melon  33.6    1

Label should give the colour of nodes (1=yellow, 0=blue).

Code for network:

 G = nx.from_pandas_edgelist(df, source='Source', target='Target', edge_attr='Weight') 

    collist = df.drop('Weight', axis=1).melt('Label').dropna() # I need this for the below lines of code because I want to draw nodes - their size - based on their degree

    degrees=[]
    for x in collist['value']:
        deg=G.degree[x]  
        degrees.append(100*deg)

    
    pos=nx.spring_layout(G)

    nx.draw_networkx_labels(G, pos, font_size=10)
    nx.draw_networkx_nodes(G, pos, nodelist=collist['value'], node_size = degrees, node_color=collist['Label'])
    nx.draw_networkx_edges(G, pos)

What this code is supposed to do is the following: the nodes should have size equal their degree (this explains degrees and collist in my code). Edges should have thickness equal to Weight. Attribute should be assigned (and updated) as in this link: (Changing attributes of nodes). Currently, my code does not include the assignment as in the link mentioned, where it was added and updated as follows:

G = nx.Graph()
G.add_node(0, weight=8)
G.add_node(1, weight=5)
G.add_node(2, weight=3)
G.add_node(3, weight=2)

nx.add_path(G, [2,5])
nx.add_path(G, [2,3])


labels = {
    n: str(n) + '\nweight=' + str(G.nodes[n]['weight']) if 'weight' in G.nodes[n] else str(n)
    for n in G.nodes
}

newWeights = \
    [
        sum( # summ for averaging
            [G.nodes[neighbor]['weight'] for neighbor in G.neighbors(node)] # weight of every neighbor
            + [G.nodes[i]['weight']] # adds the node itsself to the average
        ) / (len(list(G.neighbors(node)))+1) # average over number of neighbours+1
        if len(list(G.neighbors(node))) > 0 # if there are no neighbours
        else G.nodes[i]['weight'] # weight stays the same if no neighbours
    for i,node in enumerate(G.nodes) # do the above for every node
    ]
print(newWeights) 
for i, node in enumerate(G.nodes):
    G.nodes[i]['weight'] = newWeights[i] # writes new weights after it calculated them all.

Please note that I have more than 100 nodes so I cannot do it manually. I tried to include the Attribute in my code as follows:

G = nx.from_pandas_edgelist(df_net, source='Source', target='Target', edge_attr=['Weight'])
    nx.set_node_attributes(G, pd.Series(nodes.Attribute, index=nodes.node).to_dict(), 'Attribute')

However, I have got the error:

----> 1 network(df)

<ipython-input-72-f68985d20046> in network(dataset)
     24     degrees=[]
     25     for x in collist['value']:
---> 26         deg=G.degree[x]
     27         degrees.append(100*deg)
     28 

~/opt/anaconda3/lib/python3.8/site-packages/networkx/classes/reportviews.py in __getitem__(self, n)
    445     def __getitem__(self, n):
    446         weight = self._weight
--> 447         nbrs = self._succ[n]
    448         if weight is None:
    449             return len(nbrs) + (n in nbrs)

KeyError: 87.5

What I would like to have as expected output is a network where nodes are in the Source column and their neighbors are within the Target column. Edges have thickness based on Weight. Label gives the colour of the source, while Attribute value should be added as label and updated as in the question/answer on this link: Changing attributes of nodes .

Please see below a visual example of the type of net that I am trying to build. The attribute value in the figure is meant before the update (newWeights), and this explains why some nodes have missing value. Attribute is related to Source only, which is colored based on Label. The thickness of the edge is given by Weight.

解决方案

import networkx as nx
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({"Attribute": [87.5, 12.5, 12.5, 43.5], "Source": ["Heisenberg", "Beckham", "Messi", "water"], "Target" : ["Pauli", "Messi", "Maradona", "melon"], "Weight" : [66.3, 38.1, 12, 33.6], "Label" : [1, 0, 0,1]})

G = nx.from_pandas_edgelist(df, source='Source', target='Target', edge_attr='Weight')

source_attrs = {df.Source[i]: {"Attribute": df.Attribute[i]} for i in range(len(df.Attribute))}

target_attrs = {df.Target[i]: {"Attribute": df.Attribute[i]} for i in range(len(df.Attribute))}



nx.set_node_attributes(G, source_attrs)
nx.set_node_attributes(G, target_attrs)

degrees=[100*G.degree[i] for i in G.nodes()]
weights = [G[u][v]['Weight']/10 for u,v in G.edges()]
colors = []
for node in G.nodes():
    if node in source_attrs.keys():
        colors.append('yellow')
    else:
        colors.append('blue')

pos=nx.spring_layout(G)

pos_attrs = {}
for node, coords in pos.items():
    pos_attrs[node] = (coords[0], coords[1] + 0.08)

labels = nx.get_node_attributes(G, "Attribute")

custom_node_attrs = {}
for node, attr in labels.items():
    custom_node_attrs[node] = str(node) + str(attr)

nx.draw_networkx_labels(G, pos_attrs, labels=custom_node_attrs, font_size=10)

nx.draw_networkx_nodes(G, pos, nodelist=G.nodes(), node_size = degrees, node_color=colors)

nx.draw_networkx_edges(G,pos, width=weights)

plt.show()


这篇关于为节点分配多个属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆