如何在Python中创建“Split-Bars”图?

问题描述 投票:0回答:1

datawrapper.de

 可视化服务中,可以使用“Split-Bars”图;我想使用 matplotlib (等)在 Python 中重新创建可视化绘图类型(以编程方式)。

enter image description here

SO上没有找到相关问题。

问题描述:结构看起来是表格格式;每个单元格都填充有阴影区域;到给定的填充百分比。轴线被移除。值文本颜色根据背景颜色而变化。值文本位置根据百分比值而变化。

尝试:ChatGPT 建议ax.imshow()

生成带有颜色的每个单元格,但是(据我所知)它缺乏%填充功能。我恢复到
ax.fill_between()
,但是这只适用于沿轴(X或是)。最后我尝试了 
ax.add_patch(Rectangle(...))
,这似乎是外部“传奇”色块和内部 
ax
 %填充色块的理想选择。使用此方法的解决方案如下所示。

python data-science visualization diagram
1个回答
0
投票
图书馆代码:

import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import LinearSegmentedColormap from matplotlib.patches import Rectangle import matplotlib.font_manager as font_manager # Add every font at the specified location font_dir = ['path/to/AppData/Local/Microsoft/Windows/Fonts/'] for font in font_manager.findSystemFonts(font_dir): font_manager.fontManager.addfont(font) from matplotlib.font_manager import findfont, FontProperties font = findfont(FontProperties(family=['Roboto'])) matplotlib.rcParams['font.family'] = 'sans-serif' matplotlib.rcParams['font.sans-serif'] = 'Roboto' def plot_split_bar(data, metrics, categories, colors=[(0.6431, 0.9412, 1.0), (0.0, 0.6392, 0.6902), (0.0, 0.349, 0.3765), (0.2039, 0.749, 0.8118), (0.0, 0.4392, 0.4745), (0.3686, 0.8549, 0.9255), (0.0, 0.5373, 0.5804)], precision=2, fig_size=None): numrows = data.shape[0] numcols = data.shape[1] data_max = np.max(data)*1.025 fig, ax = plt.subplots() if fig_size: fig.set_size_inches(fig_size) # Set labels and ticks ax.set_xticks(np.arange(len(categories))-0.14) ax.set_xticklabels(categories, fontsize=8, fontname='Roboto', ha='left', va='center', y=1.001, weight='bold') ax.xaxis.tick_top() ax.xaxis.set_ticks_position('none') ax.set_yticks(np.arange(len(metrics))+0.26) ax.set_yticklabels(metrics, fontsize=7, fontname='Roboto', x=0.025, ha='right') ax.spines[['right', 'top','bottom','left']].set_visible(False) # Add text annotation for i in range(len(data)): for j in range(len(data[i])): perc = data[i][j]/data_max ax.add_patch(Rectangle((j-.29, i-.25), perc, 0.95, facecolor = colors[j], alpha=1, fill=True, )) text_pos = (j-0.26)+perc if perc < 0.5 else (j-(0.26)+.1) text_col = '#333' if perc < 0.5 else 'white' text_col = '#333' if text_col=='white' and np.mean(colors[j])>0.5 else text_col text_bold = None if perc < 0.5 else 'bold' text_perc = f'{data[i][j]:,.{precision}f}' if f'{data[i][j]:,.1f}'[-2:]!='.0' else f'{data[i][j]:,.0f}' ax.text(text_pos, i+.15, text_perc, ha='left', va='center', fontname='Roboto', color=text_col, fontsize=7, weight=text_bold) ax.grid(False) ax.set_ylim(0-0.5, numrows) ax.set_xlim(0-0.5, numcols) for j in range(len(categories)): ax.add_patch(Rectangle((j-0.31, len(data)+.4), 0.15, .7, facecolor = colors[j], clip_on=False, alpha=1, fill=True, )) plt.show()
化石燃料数据中全球二氧化碳排放量的使用:

data = pd.DataFrame(arr[1:],columns=arr[0] ).set_index('year').iloc[::-1] plot_split_bar(data=data.astype(float).to_numpy(), metrics=data.index.tolist(), categories=data.columns, precision=2, fig_size=(5, 3) )

enter image description here

与伪随机生成的数据一起使用:

cols = 3 data = pd.DataFrame( np.random.rand(5,cols), columns=[chr(65+i) for i in range(cols)]).iloc[::-1] plot_split_bar(data=data.to_numpy(), metrics=data.index.tolist(), categories=data.columns, precision=2, fig_size=(5, 1) )

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.