如何在Matplotlib中绘制带年份变化对比的树形图?
纯Matplotlib实现差值叠加树形图的思路与代码
核心思路
要实现这种「基础值+差值」的叠加树形图,无需依赖第三方树形图库,直接用Matplotlib的矩形绘制功能即可,核心步骤是:
- 拆分每个国家的2004年基础值和2022年与2004年的差值
- 按总数值占比分配每个国家的整体矩形区域
- 在每个国家的矩形内,拆分出基础值区域和差值区域,用不同颜色区分
- 添加文本标注说明对应数值
完整实现代码
import matplotlib.pyplot as plt from matplotlib.patches import Rectangle import pandas as pd # 原始数据与预处理 data = { "year": [2004, 2022, 2004, 2022, 2004, 2022], "countries": ["Denmark", "Denmark", "Norway", "Norway","Sweden", "Sweden"], "sites": [4,10,5,8,13,15] } df = pd.DataFrame(data) # 整理每个国家的基础值、差值、总数值 country_stats = df.groupby('countries').agg( base_2004=('sites', lambda x: x.iloc[0]), delta=('sites', lambda x: x.iloc[1] - x.iloc[0]), total_2022=('sites', lambda x: x.iloc[1]) ).reset_index() # 创建画布 fig, ax = plt.subplots(figsize=(10, 6)) ax.set_xlim(0, 100) ax.set_ylim(0, 50) ax.axis('off') # 隐藏坐标轴 # 配置颜色:国家基础色+差值高亮色 country_colors = { 'Denmark': '#8dd3c7', 'Norway': '#ffffb3', 'Sweden': '#bebada' } delta_highlight = '#fb8072' # 计算总数值,用于分配矩形宽度 total_total = country_stats['total_2022'].sum() current_x = 0 # 遍历每个国家绘制矩形 for _, row in country_stats.iterrows(): # 计算当前国家的整体矩形宽度(按总占比) total_width = (row['total_2022'] / total_total) * 100 # 计算基础值部分的宽度占比 base_width = (row['base_2004'] / row['total_2022']) * total_width # 绘制2004年基础值矩形 base_rect = Rectangle((current_x, 0), base_width, 50, color=country_colors[row['countries']]) ax.add_patch(base_rect) # 绘制差值部分矩形 delta_rect = Rectangle((current_x + base_width, 0), total_width - base_width, 50, color=delta_highlight) ax.add_patch(delta_rect) # 添加中心文本标注 center_x = current_x + total_width / 2 ax.text(center_x, 25, f"{row['countries']}\n2004: {row['base_2004']}\n2022: {row['total_2022']}", ha='center', va='center', fontsize=12) # 更新x轴起始位置 current_x += total_width plt.tight_layout() plt.show()
可调整的扩展方向
- 布局方向:可以把横向拆分改成纵向拆分,只需要修改
Rectangle的y轴起始位置和高度参数 - 嵌套层级:如果需要更复杂的树形嵌套(比如先按大洲再按国家),可以递归计算每个层级的矩形位置和大小
- 样式优化:可以给矩形添加边框、调整透明度,或者给差值部分添加标注(比如直接显示+X)
内容的提问来源于stack exchange,提问作者ruthpozuelo
相关产品推荐
相关产品推荐

