在桑基图中对节点进行排序

问题描述 投票:0回答:1

我正在使用 go.Plotly 尝试让节点按特定顺序输出。我希望它匹配mapping_dict顺序,或者至少使每个节点的类别保持相同的顺序。

我看过相关问题,但它们的初始结构不同,所以我不认为这是重复。如果没有请告诉我!

目标是按照 A、B、C、D、E 顺序进行(如果缺少其中之一,仍保持相同的顺序)。

函数调用 图=plot_sankey(links_dict,unique_source_targets,mapping_dict,颜色=颜色) 样本数据 映射_字典 = {'B_round1': 0, 'C_round1': 1, 'D_round1': 2, 'E_round1': 3, 'A_round2': 4, 'B_round2': 5, 'C_round2': 6, 'D_round2': 7, 'E_round2': 8, 'A_round3': 9, 'B_round3': 10, 'C_round3': 11, 'D_round3': 12, ‘E_round3’:13}

unique_source_targets=['B_round1', 'C_round1', 'D_round1', 'E_round1', 'A_round2', 'B_round2', 'C_round2', 'D_round2', 'E_round2', 'A_round3', 'B_round3', 'C_round3', 'D_round3', 'E_round3']

links_dict = {'来源': [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4 , 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], '目标': [4 , 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 9, 10, 9, 10, 11, 12 , 13, 9, 10, 11, 12, 13, 9, 10, 11, 12, 13, 9, 10, 11, 12, 13], '值': [1433, 2761, 521, 205, 117, 239 , 472, 122, 61, 31, 282, 222, 81, 71, 77, 276, 59, 41, 60, 161, 2224, 6, 548, 2449, 371, 110, 36, 155, 482, 80, 34 , 14, 105, 164, 52, 46, 30, 175, 47, 23, 37, 104]}

代码

def plot_sankey(
links_dict,
unique_source_targets,
mapping_dict,
colors=None,
fig_title='Sankey Diagram',
subtitle=''):

# Generate formatted labels using a  compute_round_labels function, which produces the label name then (value, percentage)
formatted_labels = compute_round_labels(links_dict, unique_source_targets, mapping_dict)

# Convert the unique_source_target list into the formatted labels for display
display_labels = [formatted_labels[label] for label in unique_source_targets]

fig = go.Figure(
    data=[
        go.Sankey(
            node=dict(
                pad=15,
                thickness=20,
                line=dict(color="black", width=0.5),
                label=display_labels,
                color=(colors if colors else "blue"),
            ),
            link=dict(
                source=links_dict["source"],
                target=links_dict["target"],
                value=links_dict["value"],
            ),
        )
    ]
)

# Setting the title with the subtitle using HTML formatting
full_title = f'{fig_title}<br><sub>{subtitle}</sub>'
fig.update_layout(title_text=full_title, font_size=20)

# Adjusting layout margin to accommodate title and subtitle
fig.update_layout(
    margin=dict(t=100)  # Top margin; increase if title and subtitle are clipped
)

return fig
python plotly sankey-diagram
1个回答
0
投票

基本上,你几乎是对的。您必须在桑基图中强制执行特定的节点顺序,因此您需要确保

links_dict
中源节点和目标节点的索引与
mapping_dict
中指定的所需出现顺序一致。这是一种方法。您需要自己添加这些值

import plotly.graph_objects as go
import pandas as pd

def plot_sankey(links_dict, unique_source_targets, mapping_dict, colors=None, fig_title='Sankey Diagram', subtitle=''):
    custom_order = ['A', 'B', 'C', 'D', 'E']
    sorted_items = sorted(mapping_dict.items(), key=lambda x: (x[0][-7:], custom_order.index(x[0][0])))
    mapping_dict = {item[0]: i for i, item in enumerate(sorted_items)}

    links_dict['source'] = [mapping_dict[unique_source_targets[x]] for x in links_dict['source']]
    links_dict['target'] = [mapping_dict[unique_source_targets[x]] for x in links_dict['target']]

    display_labels = [x.split('_')[0] + ' round' + x[-1] for x in unique_source_targets]  # Simplified label generation for example

    fig = go.Figure(data=[
        go.Sankey(
            node=dict(
                pad=15, thickness=20,
                line=dict(color="black", width=0.5),
                label=display_labels,
                color=colors if colors else ["blue"]*len(display_labels),
            ),
            link=dict(
                source=links_dict['source'],
                target=links_dict['target'],
                value=links_dict['value']
            )
        )
    ])

    full_title = f'{fig_title}<br><sub>{subtitle}</sub>'
    fig.update_layout(title_text=full_title, font_size=20)
    fig.update_layout(margin=dict(t=100))

    return fig

mapping_dict = {'B_round1': 0, 'C_round1': 1, 'D_round1': 2, 'E_round1': 3, 'A_round2': 4, 'B_round2': 5, 
                'C_round2': 6, 'D_round2': 7, 'E_round2': 8, 'A_round3': 9, 'B_round3': 10, 'C_round3': 11, 
                'D_round3': 12, 'E_round3': 13}
unique_source_targets = list(mapping_dict.keys())
links_dict = {
    'source': [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8],
    'target': [4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 9, 10, 9, 10, 11, 12, 13, 9, 10, 11, 12, 13, 9, 10, 11, 12, 13, 9, 10, 11, 12, 13],
    'value': [1433, 2761, 521, 205, 117, 239, 472, 122, 61, 31, 282, 222, 81, 71, 77, 276, 59, 41, 60, 161, 2224, 6, 548, 2449, 371, 110, 36, 155, 482, 80, 34, 14, 105, 164, 52, 46, 30, 175, 47, 23, 37, 104]
}

fig = plot_sankey(links_dict, unique_source_targets, mapping_dict, colors=['red', 'blue']*7)
fig.show()

© www.soinside.com 2019 - 2024. All rights reserved.