Python多级Treemap自定义标签实现技术求助
多级汽车Treemap绘制问题
我需要基于下方的汽车品牌(Make)、车型(Type)和数量(count)数据集绘制多级Treemap,尝试过plotly.express和matplotlib-extra库但没解决问题。希望自定义标签格式为「品牌\n数量」,但Squarify不支持多级结构,现有代码片段如下:
# labels = [f'{make}\n{count}' for make, count in zip(car_cmt_df['Make'].tolist(), car_cmt_df['Type'].tolist())]
数据集
| Make | Type | count | |
|---|---|---|---|
| 0 | Audi | Convertible | 79 |
| 1 | Audi | Coupe | 210 |
| 2 | Audi | Hatchback | 41 |
| 3 | Audi | Sedan | 216 |
| 4 | Audi | Wagon | 43 |
| 5 | BMW | Convertible | 162 |
| 6 | BMW | Coupe | 86 |
| 7 | BMW | SUV | 123 |
| 8 | BMW | Sedan | 118 |
| 9 | BMW | Wagon | 42 |
| 10 | Chevrolet | Convertible | 85 |
| 11 | Chevrolet | Coupe | 45 |
| 12 | Chevrolet | Crew Cab | 85 |
| 13 | Chevrolet | Extended Cab | 87 |
| 14 | Chevrolet | Regular Cab | 82 |
| 15 | Chevrolet | SS | 119 |
| 16 | Chevrolet | SUV | 81 |
| 17 | Chevrolet | Sedan | 171 |
| 18 | Chevrolet | Van | 65 |
| 19 | Chevrolet | Z06 | 38 |
| 20 | Chevrolet | ZR1 | 47 |
| 21 | Fisker | Sedan | 44 |
| 22 | HUMMER | Crew Cab | 83 |
| 23 | Ram | Minivan | 41 |
| 24 | Tesla | Sedan | 39 |
参考效果

可行解决方案建议
方案1:使用Plotly Express实现多级Treemap(推荐)
Plotly原生支持多级分层的Treemap,且可以自定义标签格式,步骤如下:
- 预处理数据集:确保
count列是数值类型(原数据中Audi Coupe的210 V需修正为210) - 构建分层路径:通过
path参数指定['Make', 'Type']作为两级层级 - 自定义标签:用
text参数设置「品牌\n数量」格式,结合texttemplate控制显示
示例代码:
import plotly.express as px import pandas as pd # 加载并修正数据集 car_cmt_df = pd.DataFrame([ ["Audi", "Convertible", 79], ["Audi", "Coupe", 210], ["Audi", "Hatchback", 41], ["Audi", "Sedan", 216], ["Audi", "Wagon", 43], ["BMW", "Convertible", 162], ["BMW", "Coupe", 86], ["BMW", "SUV", 123], ["BMW", "Sedan", 118], ["BMW", "Wagon", 42], ["Chevrolet", "Convertible", 85], ["Chevrolet", "Coupe", 45], ["Chevrolet", "Crew Cab", 85], ["Chevrolet", "Extended Cab", 87], ["Chevrolet", "Regular Cab", 82], ["Chevrolet", "SS", 119], ["Chevrolet", "SUV", 81], ["Chevrolet", "Sedan", 171], ["Chevrolet", "Van", 65], ["Chevrolet", "Z06", 38], ["Chevrolet", "ZR1", 47], ["Fisker", "Sedan", 44], ["HUMMER", "Crew Cab", 83], ["Ram", "Minivan", 41], ["Tesla", "Sedan", 39] ], columns=["Make", "Type", "count"]) # 绘制多级Treemap fig = px.treemap( car_cmt_df, path=['Make', 'Type'], values='count', text=['<b>{}</b>\n{}'.format(m, c) for m, c in zip(car_cmt_df['Make'], car_cmt_df['count'])], texttemplate='%{text}', hover_data={'count': True} ) # 调整布局,隐藏冗余图例 fig.update_layout( margin=dict(t=50, l=25, r=25, b=25), showlegend=False ) fig.show()
方案2:使用Squarify结合Matplotlib手动绘制多级结构
若坚持用Matplotlib+Squarify,需手动分层绘制:
- 计算每个品牌的总数量,绘制一级Treemap(品牌层级)
- 对每个品牌的子车型,在对应品牌方块内绘制二级Treemap
- 在每个方块中心添加「品牌\n数量」自定义标签
核心代码片段:
import matplotlib.pyplot as plt import squarify import pandas as pd # 加载并修正数据集 car_cmt_df = pd.DataFrame([...]) # 同方案1的数据集 # 计算品牌总数量 brand_totals = car_cmt_df.groupby('Make')['count'].sum().reset_index() # 绘制一级Treemap(品牌层) fig, ax = plt.subplots(figsize=(12, 8)) rects = squarify.plot( sizes=brand_totals['count'], label=brand_totals['Make'], ax=ax, alpha=0.7 ) ax.set_axis_off() # 遍历每个品牌方块,绘制二级车型Treemap # 需手动匹配方块坐标与对应品牌的子车型数据,此处省略坐标匹配细节 # 例如:对每个品牌,筛选其下的车型数据,在对应的rect区域内绘制子treemap plt.show()
关键注意事项
- 必须确保
count列是纯数值类型,异常值(如原数据中的210 V)需提前修正 - Plotly方案无需手动处理坐标,自动适配多级结构,交互性更强,更贴近参考图效果
- 若需要静态图,Plotly可直接导出为PNG/SVG格式
内容的提问来源于stack exchange,提问作者B L Praveen
相关产品推荐
相关产品推荐

