【发布时间】:2021-04-26 23:52:25
【问题描述】:
我想为我的节点分配一个属性。目前我正在使用以下数据样本创建一个网络:
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
标签应该给出节点的颜色(1=黄色,0=蓝色)。
网络代码:
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)
这段代码应该做的是:节点的大小应该等于它们的度数(这在我的代码中解释了度数和collist)。边的厚度应等于Weight。 Attribute 应在此链接中分配(和更新):(Changing attributes of nodes)。目前,我的代码不包括提到的链接中的分配,其中添加和更新如下:
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.
请注意,我有超过 100 个节点,所以我无法手动完成。 我尝试在我的代码中包含以下属性:
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')
但是,我得到了错误:
----> 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
我希望得到的输出是一个网络,其中节点位于“源”列中,而它们的邻居位于“目标”列中。边缘的厚度基于权重。标签给出源的颜色,而属性值应作为标签添加并更新,如此链接上的问题/答案:Changing attributes of nodes。
请在下面查看我正在尝试构建的网络类型的视觉示例。图中的属性值是指更新前的(newWeights),这就解释了为什么有些节点有缺失值。 Attribute 只与 Source 相关,Source 根据 Label 着色。边缘的厚度由权重给出。
【问题讨论】:
-
请遵循已接受的答案,即stackoverflow.com/a/42558578/11339311,而不是添加属性问题中的另一个(没有帮助的答案)。
-
我更新了问题,包括我在遵循您提到的链接中接受的答案后所做的更改。我想我仍然错过或做错了什么
-
您能否为您的最小示例数据框添加所需的
networkx图。所以应该创建哪些边/节点属性(在应用这个平均计算之前,你已经有了一个解决方案)。因为目前比较混乱,贝克汉姆应该有属性12.5还是23.5?重量只是目标或源的音符属性 - 还是边缘?我也不清楚你现在所说的“宽度”是什么意思,如果你希望创建一个图形,其中每条边都具有给定属性的长度,那么遗憾的是(容易/自动)不可能。 -
我在数据框中发现了两个错误,现在我已修复。非常感谢@Sparky05。我包含了一个我正在尝试构建的网络示例。
Attribute=是我需要根据newWeights计算的。它可以在节点外部或内部(没有Attribute=)。在宽度上,我的意思是厚度。贝克汉姆应该有属性 12.5 而不是 23.5(固定)。非常感谢您,也感谢您在我报告示例时发现了这些错别字。