【问题标题】:ValueError due to a missing element in color map由于颜色图中缺少元素导致的 ValueError
【发布时间】:2021-09-30 19:14:13
【问题描述】:

我需要构建一个网络,其中节点(来自df1)根据来自不同数据集(df2)的标签具有一些特定的颜色。在df1 中,并非所有节点都已在df2 中分配了标签(例如,因为它们还没有被标记,所以它们当前具有 nan 值)。 下面的代码应该提供一个很好的例子来说明我的意思:

import networkx as nx
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt, colors as mcolor

# Sample DataFrames
df1 = pd.DataFrame({
    'Node': ['A', 'A', 'B', 'B', 'B', 'Z'],
    'Edge': ['B', 'D', 'N', 'A', 'X', 'C']
})
df2 = pd.DataFrame({
    'Nodes': ['A', 'B', 'C', 'D', 'N', 'S', 'X'],
    'Attribute': [-1, 0, -1.5, 1, 1, 9, 0]
})

# Simplified construction of `colour_map`
uni_val = df2['Attribute'].unique()
colors = plt.cm.jet(np.linspace(0, 1, len(uni_val)))
# Map colours to_hex then zip with
mapper = dict(zip(uni_val, map(mcolor.to_hex, colors)))
color_map =df2.set_index('Nodes')['Attribute'].map(mapper).fillna('black')


G = nx.from_pandas_edgelist(df1, source='Node', target='Edge')
# Add Attribute to each node
nx.set_node_attributes(G, color_map, name="colour")

# Then draw with colours based on attribute values:
nx.draw(G,
        node_color=nx.get_node_attributes(G, 'colour').values(),
        with_labels=True)

plt.show()

Z 不是 df2,因为创建 df2 时只考虑了非 NA 值。 我想将黑色分配给未标记的节点,即那些不在df2 中的节点。 尝试运行上面的代码,我收到了这个错误:

ValueError: 'c' argument has 7 elements, which is inconsistent with 'x' and 'y' with size 8.

很明显,这个错误是由于缺少添加颜色黑色引起的,不包含在color_map中。 我不清楚如何解决这个问题。我希望能帮助您解决这个问题。

【问题讨论】:

    标签: python pandas matplotlib networkx


    【解决方案1】:

    由于Z 不在df2 中,而是其中一个节点,我们应该,而不是专门从df2 创建属性,我们应该reindex 来自nodescolor_map 带有@ 的节点987654332@:

    # Create graph before color map:
    G = nx.from_pandas_edgelist(df1, source='Node', target='Edge')
    # Create Colour map. Ensure all nodes have a value via reindex using nodes
    color_map = (
        df2.set_index('Nodes')['Attribute'].map(mapper)
            .reindex(G.nodes(), fill_value='black')
    )
    


    color_map 没有重新索引

    df2.set_index('Nodes')['Attribute'].map(mapper)
    
    Nodes
    A    #000080
    B    #0080ff
    C    #7dff7a
    D    #ff9400
    N    #ff9400
    S    #800000
    X    #0080ff
    Name: Attribute, dtype: object
    

    nodes(此处使用节点,因为这将是图中的所有节点,而不仅仅是 df2 中的节点)

    G.nodes()
    
    ['A', 'B', 'D', 'N', 'X', 'Z', 'C']
    

    reindex 确保所有节点都存在于映射中:

    df2.set_index('Nodes')['Attribute'].map(mapper).reindex(G.nodes(), fill_value='black')
    
    Nodes
    A    #000080
    B    #0080ff
    D    #ff9400
    N    #ff9400
    X    #0080ff
    Z      black  # <- Missing Nodes are added with specified value
    C    #7dff7a
    Name: Attribute, dtype: object
    

    完整代码:

    import networkx as nx
    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt, colors as mcolor
    
    # Sample DataFrames
    df1 = pd.DataFrame({
        'Node': ['A', 'A', 'B', 'B', 'B', 'Z'],
        'Edge': ['B', 'D', 'N', 'A', 'X', 'C']
    })
    df2 = pd.DataFrame({
        'Nodes': ['A', 'B', 'C', 'D', 'N', 'S', 'X'],
        'Attribute': [-1, 0, -1.5, 1, 1, 9, 0]
    })
    
    # Simplified construction of `colour_map`
    uni_val = df2['Attribute'].unique()
    colors = plt.cm.jet(np.linspace(0, 1, len(uni_val)))
    # Map colours to_hex then zip with
    mapper = dict(zip(uni_val, map(mcolor.to_hex, colors)))
    
    G = nx.from_pandas_edgelist(df1, source='Node', target='Edge')
    # Create Colour map. Ensure all nodes have a value via reindex
    color_map = (
        df2.set_index('Nodes')['Attribute'].map(mapper)
            .reindex(G.nodes(), fill_value='black')
    )
    # Add Attribute to each node
    nx.set_node_attributes(G, color_map, name="colour")
    
    # Then draw with colours based on attribute values:
    nx.draw(G,
            node_color=nx.get_node_attributes(G, 'colour').values(),
            with_labels=True)
    
    plt.show()
    

    【讨论】:

    • 非常感谢,亨利!一如既往,很好且解释清楚的答案!
    • 抱歉,Henry,在使用完整数据集运行结束时,我收到此错误:ValueError: 'c' argument must be a color, a sequence of colors, or a sequence of numbers, not dict_values。你知道为什么吗? ----&gt; 6 nx.draw(G, node_color=nx.get_node_attributes(G, 'colour').values(),with_labels=True)
    • 你可以试试node_color=list(nx.get_node_attributes(G, 'colour').values())。我不知道matplotlib 的哪个版本开始允许任何集合分散。
    • 不幸的是它返回了同样的错误。请问您使用的是哪个版本的matplotlib?我的是 3.3.4
    • 那个版本应该可以正常工作。如果您将无效的颜色代码作为属性,也会发生此错误。就像在上面的代码中更改为fill_value='nonsense' 会产生该错误。仔细检查您的 color_map 并确保所有代码看起来都是有效的十六进制或颜色代码。
    猜你喜欢
    • 1970-01-01
    • 2020-06-18
    • 2018-03-04
    • 2023-02-10
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多