You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Plotly Sankey图节点按A/B/C/D/E或mapping_dict顺序排列?

如何让Plotly Sankey图节点按指定顺序排列?

我正在使用go.Plotly绘制Sankey图,希望节点按指定顺序输出:要么匹配mapping_dict的顺序,要么至少让每个节点的类别保持A、B、C、D、E的固定顺序(即使某个类别缺失也维持该顺序)。已查阅过相关问题,但初始结构与我的场景不同,因此不认为这是重复问题。

函数调用

fig = plot_sankey(links_dict, unique_source_targets, mapping_dict, colors=colors)

示例数据

mapping_dict

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

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 = {
    '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]
}

核心代码

plot_sankey函数

import plotly.graph_objects as go

def plot_sankey(
    links_dict,
    unique_source_targets,
    mapping_dict,
    colors=None,
    fig_title='Sankey Diagram',
    subtitle=''
):
    # 生成带数值和百分比的格式化标签
    formatted_labels = compute_round_labels(links_dict, unique_source_targets, mapping_dict)
    
    # 将unique_source_target列表转换为用于展示的格式化标签
    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"],
                ),
            )
        ]
    )

    # 使用HTML格式设置标题和副标题
    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

compute_labels函数

from collections import defaultdict

def compute_labels(links_dict, unique_source_targets, mapping_dict):
    category_totals = defaultdict(int)
    label_counts = defaultdict(int)

    # 针对_round1和_round2,按源索引累加数值
    for source, value in zip(links_dict['source'], links_dict['value']):
        label = unique_source_targets[source]
        category_type = label.rsplit('_', 1)[1]  # 提取轮次类型,如'round1'
        category_totals[category_type] += value
        label_counts[label] += value

    # 针对_round3,使用目标索引做特殊处理
    for target, value in zip(links_dict['target'], links_dict['value']):
        # 检查目标索引是否存在于mapping_dict的值中
        if target in mapping_dict.values():
            # 匹配目标索引对应的标签
            label = next((label for label, index in mapping_dict.items() if index == target), None)
            if label and label.endswith('round3'):  # 确保是_round3标签
                category_type = label.rsplit('_', 1)[1]
                category_totals[category_type] += value
                label_counts[label] += value

    # 格式化标签,添加数值和百分比
    formatted_labels = {}
    for label, count in label_counts.items():
        category_type = label.rsplit('_', 1)[1]
        round_total = category_totals[category_type]
        percentage = int(round((count / round_total) * 100, 0))
        formatted_labels[label] = f"{label} ({count}, {percentage}%)"

    return formatted_labels

内容的提问来源于stack exchange,提问作者CiviLearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:14:58