如何用Matplotlib在Python中创建Split-Bars图表?
如何用Matplotlib复现Datawrapper的Split-Bars图表类型
我需要在Python的Matplotlib中复现Datawrapper的Split-Bars图表,该图表以表格形式展示,每个单元格根据数值比例填充深色区域,文本颜色随背景自动调整,且无轴线干扰。
数据集
A B C D 0.52072 0.08571 0.70141 0.01849 0.46156 0.47112 0.92709 0.24230 0.82056 0.07003 0.14328 0.79489 0.64635 0.72227 0.12274 0.06919 0.83555 0.50729 0.65337 0.62428 0.38232 0.19952 0.24025 0.47434 0.97861 0.53296 0.43911 0.40135 0.93070 0.73063 0.06899 0.00429 0.08514 0.98483 0.80090 0.27527 0.93412 0.05890 0.68416 0.81203 0.78269 0.55302 0.30861 0.19934
已尝试的步骤
- 在Stack Overflow未找到相关问题
- 未搜索到可直接复现该图表的开源代码或库
- 生成式AI服务未给出正确实现
- 自行探索方向:使用
ax.add_patch(Rectangle(...))绘制单元格背景与填充块,调整文本位置和颜色
解决方案代码
import matplotlib.pyplot as plt from matplotlib.patches import Rectangle import pandas as pd # 读取数据集 data = """A B C D 0.52072 0.08571 0.70141 0.01849 0.46156 0.47112 0.92709 0.24230 0.82056 0.07003 0.14328 0.79489 0.64635 0.72227 0.12274 0.06919 0.83555 0.50729 0.65337 0.62428 0.38232 0.19952 0.24025 0.47434 0.97861 0.53296 0.43911 0.40135 0.93070 0.73063 0.06899 0.00429 0.08514 0.98483 0.80090 0.27527 0.93412 0.05890 0.68416 0.81203 0.78269 0.55302 0.30861 0.19934""" df = pd.read_csv(pd.compat.StringIO(data), sep='\s+') # 图表参数设置 cell_width = 1 cell_height = 1 bg_color = '#e0e0e0' fill_color = '#333333' text_color_light = '#ffffff' text_color_dark = '#000000' n_rows, n_cols = df.shape # 创建画布和轴 fig, ax = plt.subplots(figsize=(n_cols * cell_width * 1.2, n_rows * cell_height * 1.2)) # 隐藏轴线和刻度 ax.set_xlim(0, n_cols * cell_width) ax.set_ylim(0, n_rows * cell_height) ax.set_xticks([]) ax.set_yticks([]) for spine in ax.spines.values(): spine.set_visible(False) # 遍历绘制每个单元格 for i in range(n_rows): for j in range(n_cols): # 计算单元格坐标(从下往上绘制行) x = j * cell_width y = (n_rows - i - 1) * cell_height # 绘制背景矩形 bg_rect = Rectangle((x, y), cell_width, cell_height, color=bg_color) ax.add_patch(bg_rect) # 获取当前单元格数值 val = df.iloc[i, j] # 绘制填充矩形(宽度为数值比例) fill_rect = Rectangle((x, y), cell_width * val, cell_height, color=fill_color) ax.add_patch(fill_rect) # 确定文本位置和颜色 if val > 0.5: # 填充占比超过50%,文本放在填充区域,用白色 text_x = x + cell_width * val * 0.5 text_color = text_color_light else: # 填充占比不足50%,文本放在未填充区域,用黑色 text_x = x + cell_width * val + (cell_width * (1 - val)) * 0.5 text_color = text_color_dark # 添加格式化后的文本 ax.text(text_x, y + cell_height / 2, f'{val:.2f}', ha='center', va='center', color=text_color, fontsize=10) # 添加列标题 for j, col in enumerate(df.columns): ax.text(j * cell_width + cell_width / 2, n_rows * cell_height - 0.2 * cell_height, col, ha='center', va='center', fontweight='bold', fontsize=11) plt.tight_layout() plt.show()
实现说明
- 单元格绘制:使用
Rectangle分别绘制灰色背景和深色填充块,填充块的宽度由单元格数值比例决定 - 文本适配:根据数值大小自动切换文本颜色(深色区域用白色文本,浅色区域用黑色文本),并将文本放置在对比明显的区域,保证可读性
- 样式优化:隐藏所有轴线、刻度,添加列标题,模拟表格式的视觉效果
- 布局调整:通过
tight_layout()自动调整布局,避免元素重叠
内容的提问来源于stack exchange,提问作者pds
相关产品推荐
相关产品推荐

