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

Python Plotly Treemap颜色变量未累加子节点值问题排查

解决Plotly Treemap父节点颜色未按子节点Sales_Amount累加值显示的问题

问题说明

使用Plotly绘制Treemap时,设置三个分类变量作为父子层级,用Sales_Quantity映射面积,Sales_Amount映射颜色。预期父节点颜色对应累加所有子节点Sales_Amount后的总值,但实际未实现——父节点hover显示的数值甚至低于单个子节点,比如Cat_1049总销售额约61.9M,但颜色仅对应5.4M。尝试过branchvalues参数、清理NaN、重排数据、使用go.Treemap等方法,均未解决。

示例数据

{'Category': {1171: 'Cat_1049',
  1172: 'Cat_1049',
  1173: 'Cat_1049',
  1174: 'Cat_1049',
  1175: 'Cat_1049'},
 'SubCategory_1': {1171: 6754, 1172: 6752, 1173: 6748, 1174: 6746, 1175: 6742},
 'SubCategory_2': {1171: 'MCW-145',
  1172: 'MCW-145',
  1173: 'MCW-145',
  1174: 'MCW-145',
  1175: 'MCW-141'},
 'Sales_Amount': {1171: 13509.043,
  1172: 8662.54,
  1173: 92531.29,
  1174: 11312.07,
  1175: 6427.037},
 'Sales_Quantity': {1171: 6, 1172: 4, 1173: 38, 1174: 5, 1175: 3}}

原代码

fig = px.treemap(df_test, path= 
[px.Constant('All'),'Category', 'SubCategory_1','SubCategory_2'], 
                 values='Sales_Quantity',
                 color='Sales_Amount',
color_continuous_scale=px.colors.sequential.Turbo)
fig.update_layout(legend_title="",
    autosize=False,
    width=1440,
    height=900,
    margin=dict(
        l=0,
        r=15,
        b=10,
        t=30,
        pad=3
    ),title={'text':(f'Sales Amount and Quantities by Groups'), 
           'y':0.99,'x':0.5,'xanchor':'center',
'yanchor': 'top','font_size':20},
    legend=dict(orientation="h"))

fig.show()

解决方案

Plotly Express的Treemap默认不会自动累加color字段的父节点值,必须手动预处理数据,计算各层级的累加值,再用go.Treemap手动构建节点,确保父节点的颜色对应子节点的销售额总和。

步骤1:预处理数据,生成所有层级的节点

import pandas as pd
import plotly.graph_objects as go

# 转换示例数据为DataFrame
df = pd.DataFrame(data)

# 存储所有层级的节点数据
nodes = []

# 1. 叶子节点:SubCategory_2层级
for _, row in df.iterrows():
    node_id = f"{row['Category']}|{row['SubCategory_1']}|{row['SubCategory_2']}"
    parent_id = f"{row['Category']}|{row['SubCategory_1']}"
    nodes.append({
        'id': node_id,
        'parent': parent_id,
        'value': row['Sales_Quantity'],
        'sales_amount': row['Sales_Amount'],
        'label': row['SubCategory_2']
    })

# 2. SubCategory_1层级:累加子节点的销售额和销量
sc1_groups = df.groupby(['Category', 'SubCategory_1']).agg(
    total_quantity=('Sales_Quantity', 'sum'),
    total_amount=('Sales_Amount', 'sum')
).reset_index()
for _, row in sc1_groups.iterrows():
    node_id = f"{row['Category']}|{row['SubCategory_1']}"
    parent_id = row['Category']
    nodes.append({
        'id': node_id,
        'parent': parent_id,
        'value': row['total_quantity'],
        'sales_amount': row['total_amount'],
        'label': str(row['SubCategory_1'])
    })

# 3. Category层级:累加子节点的销售额和销量
cat_groups = df.groupby('Category').agg(
    total_quantity=('Sales_Quantity', 'sum'),
    total_amount=('Sales_Amount', 'sum')
).reset_index()
for _, row in cat_groups.iterrows():
    node_id = row['Category']
    parent_id = 'All'
    nodes.append({
        'id': node_id,
        'parent': parent_id,
        'value': row['total_quantity'],
        'sales_amount': row['total_amount'],
        'label': row['Category']
    })

# 4. 顶层节点All:累加所有数据的销售额和销量
all_total = df.agg(
    total_quantity=('Sales_Quantity', 'sum'),
    total_amount=('Sales_Amount', 'sum')
)
nodes.append({
    'id': 'All',
    'parent': '',
    'value': all_total['total_quantity'],
    'sales_amount': all_total['total_amount'],
    'label': 'All'
})

# 转换为DataFrame方便后续调用
nodes_df = pd.DataFrame(nodes)

步骤2:用go.Treemap绘制图表

fig = go.Figure(go.Treemap(
    ids=nodes_df['id'],
    parents=nodes_df['parent'],
    values=nodes_df['value'],
    labels=nodes_df['label'],
    marker=dict(
        colors=nodes_df['sales_amount'],
        colorscale='Turbo',
        colorbar=dict(title='Sales Amount')
    ),
    textinfo='label+value+percent parent',
    hovertemplate='<b>%{label}</b><br>' +
                  'Sales Quantity: %{value}<br>' +
                  'Sales Amount: %{customdata:,.2f}<extra></extra>',
    customdata=nodes_df['sales_amount']
))

fig.update_layout(
    legend_title="",
    autosize=False,
    width=1440,
    height=900,
    margin=dict(l=0, r=15, b=10, t=30, pad=3),
    title={
        'text': 'Sales Amount and Quantities by Groups',
        'y': 0.99, 'x': 0.5, 'xanchor': 'center',
        'yanchor': 'top', 'font_size': 20
    },
    legend=dict(orientation="h")
)

fig.show()

方案说明

  • 手动构建了从叶子节点到顶层的所有层级数据,确保每个父节点的sales_amount是其所有子节点的累加值
  • 使用go.Treemap直接指定每个节点的id、parent、values和colors,完全控制节点的数值映射
  • 通过hovertemplate自定义悬浮提示,显示正确的累加销售额数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:35:17