【问题标题】:KeyError caused by a wrong attribute assignment within the network?网络内属性分配错误导致的KeyError?
【发布时间】:2021-04-09 15:36:01
【问题描述】:

我的数据集格式不正确,因为它有以下列

Source   Target  Label_Source    Label_Target
    E   N   0.0 0.0
    A   B   1.0 1.0
    A   C   1.0 0.0
    A   D   1.0 0.0
    A   N   1.0 0.0
    S   G   0.0 0.0
    S   L   0.0 1.0
    S   C   0.0 0.0

Label_Source 和 Label_Target 是节点属性 Label_Source 是源的属性,而 Label_Target 是目标的属性。 尝试复制以下项目:https://www.fatalerrors.org/a/python-networkx-learning-notes.html,我遇到了一些错误,包括由于 Label_Source 导致的 KeyError。正如这个答案中所解释的:KeyError after re-running the (same) code,问题似乎是由边缘/节点属性中的错误分配引起的,因为代码正在读取 Label_Source 作为边缘的属性。 正如我所说,我想复制该项目,因此任何可以使其成为可能的格式都是可以接受的。但是,我真的很感激有人可以解释(不仅仅是展示)如何解决这个问题,因为我不清楚是什么驱动了它。 到目前为止我所做的如下所示:

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

G = nx.from_pandas_edgelist(filtered, 'Source', 'Target',  edge_attr=True)
df_pos = nx.spring_layout(G,k = 0.3) 

nx.draw_networkx(G, df_pos)
plt.show()

node_color = [
    '#1f78b4' if G.nodes[v]["Label_Source"] == 0 # actually this assignment should just Label and it should include also Target, so the whole list of nodes and their labels. A way to address this would be to select all distinct nodes in the network and their labels
    else '#33a02c' for v in G]

# Iterate through all edges
for v, w in G.edges:
    if G.nodes[v]["Label_Source"] == G.nodes[w]["Label_Source"]: # this should refer to all the Labels 
        G.edges[v, w]["internal"] = True
    else:
        G.edges[v, w]["internal"] = False

如果您能帮助我了解如何解决问题并复制代码,那就太好了。我猜这个错误也在于尝试遍历字符串而不是索引。

【问题讨论】:

    标签: python pandas networkx


    【解决方案1】:

    创建图表后:

    G = nx.from_pandas_edgelist(filtered, 'Source', 'Target',  edge_attr=True)
    df_pos = nx.spring_layout(G,k = 0.3) 
    

    你有以下属性:

    # For edges:
    print(G.edges(data=True))
    [('E', 'N', {'Label_Source': 0.0, 'Label_Target': 0.0}),
     ('N', 'A', {'Label_Source': 1.0, 'Label_Target': 0.0}),  # Problem here
     ('A', 'B', {'Label_Source': 1.0, 'Label_Target': 1.0}),
     ('A', 'C', {'Label_Source': 1.0, 'Label_Target': 0.0}),
     ('A', 'D', {'Label_Source': 1.0, 'Label_Target': 0.0}),
     ('C', 'S', {'Label_Source': 0.0, 'Label_Target': 0.0}),
     ('S', 'G', {'Label_Source': 0.0, 'Label_Target': 0.0}),
     ('S', 'L', {'Label_Source': 0.0, 'Label_Target': 1.0})]
    
    # For nodes:
    print(G.nodes(data=True))
    [('E', {}), ('N', {}), ('A', {}), ('B', {}),
     ('C', {}), ('D', {}), ('S', {}), ('G', {}), ('L', {})]
    

    如您所见,节点没有属性。您必须将 Label_xxx 值从边缘属性复制到右节点:

    # Don't use it, check update below
    for source, target, attribs in G.edges(data=True):
        G.nodes[source]['Label'] = int(attribs['Label_Source'])
        G.nodes[target]['Label'] = int(attribs['Label_Target'])
    
    print(G.nodes(data=True))
    [('E', {'Label': 0}), ('N', {'Label': 1}), ('A', {'Label': 1}),
     ('B', {'Label': 1}), ('C', {'Label': 0}), ('D', {'Label': 0}),
     ('S', {'Label': 0}), ('G', {'Label': 0}), ('L', {'Label': 1})]
    

    现在您可以为图表的每个节点设置颜色:

    node_color = ['#1f78b4' if v == 0 else '#33a02c'
                  for v in nx.get_node_attributes(G, 'Label').values()]
    
    print(node_color)
    ['#1f78b4', '#33a02c', '#33a02c', '#33a02c',
     '#1f78b4', '#1f78b4', '#1f78b4', '#1f78b4', '#33a02c']
    

    最后一步:

    nx.draw_networkx(G, df_pos, label=True, node_color=node_color)
    plt.show()
    

    更新

    我认为将颜色分配给节点的代码存在一些问题。一些节点的颜色错误(例如,它们应该是绿色的,它们应该是蓝色的)。

    问题在于存储为('N', 'A') -> (1, 0) 的边('A', 'N') -> (1, 0),因为您的图形不是有向的,因此边是('A', 'N') 还是('N', 'A') 并不重要。如果这对您的问题有意义,您可以通过使用选项 create_using=nx.DiGraph 创建图表来解决此问题。

    另一种解决方案是创建Label 属性,而不是从边缘属性,而是从您的数据框,如我的previous answer 建议:

    for _, sr in df.iterrows():
        G.nodes[sr['Source']]['Label'] = int(sr['Label_Source'])
        G.nodes[sr['Target']]['Label'] = int(sr['Label_Target'])
    
    print(G.nodes(data=True))
    [('E', {'Label': 0}), ('N', {'Label': 0}), ('A', {'Label': 1}),
     ('B', {'Label': 1}), ('C', {'Label': 0}), ('D', {'Label': 0}),
     ('S', {'Label': 0}), ('G', {'Label': 0}), ('L', {'Label': 1})]
    

    现在,每个节点都有正确的Label 属性:

    【讨论】:

    • @LdM。你现在清楚了吗?
    • 是的,你完全正确。我试图了解内部/外部边缘
    • 我不确定是否正确理解内部/外部部分。应该怎么做?
    • 根据我从该代码中了解到的情况,它应该识别链接来自不同类的两个(或多个)节点的节点。像“桥”节点。也许有更好的算法来做到这一点。我在网上没有找到很多。我想识别两个类之间的节点
    • 我更新了我的答案。请您检查一下,如果有些地方不清楚,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 2016-11-28
    • 2021-07-25
    • 2016-06-17
    • 2020-07-07
    相关资源
    最近更新 更多