为节点分配多个属性 [英] Assigning multiple attributes to nodes
问题描述
我想为我的节点分配一个属性.目前我正在使用以下数据示例创建网络:
属性源目标权重标签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屋!