如何创建分类进度条

How to create a categorized progress bar

我正在尝试创建一个状态栏,该状态栏与我们目前在其他报告工具中看到的类似(见附图)。我想使用 matplotlib 将其生成为图像,这样它就可以在多个不同的地方和报告中使用。

我找不到一个很好的指南来指导我如何使用 Matplotlib 来做到这一点。我将数据传递为:

results = {'pass': 5, 'fail':18, 'na': 10, 'todo': 187, 'blocked': 12, 'aborted': 10}

我希望它看起来类似于此图表:

谁能指导我找到合适的资源?

我获取了 documentation 的代码并进行了一些更改,以便将其应用于您的案例。

import matplotlib.pyplot as plt
import numpy as np

results = {'Pass': 5, 'Fail':18, 'Na': 10, 'Todo': 187, 'Blocked': 12, 'Aborted': 10}

category_names = [f'{value} {category.upper()}' for category, value in results.items()]

results = {'1': list(results.values())}

labels = list(results.keys())
data = np.array(list(results.values()))
data_cum = data.cumsum(axis = 1)
category_colors = plt.get_cmap('RdYlGn')(np.linspace(0.15, 0.85, data.shape[1]))

fig = plt.figure(figsize = (10, 2))
ax = fig.add_axes([0.1, 0.4, 0.8, 0.4])

ax.axis('off')

for i, (colname, color) in enumerate(zip(category_names, category_colors)):
    widths = data[:, i]
    starts = data_cum[:, i] - widths
    ax.barh(labels, widths, left = starts, height = 0.5, label = colname, color = color)

ax.legend(ncol = len(category_names), bbox_to_anchor = (0, 0), loc = 'upper left', fontsize = 10, frameon = False)

plt.show()

如果你也想格式化图例,你可以将上面的 ax.legend 行替换为(你必须用 from matplotlib import transforms 导入 transforms):

handles, labels = ax.get_legend_handles_labels()

for label, color, position in zip(labels, category_colors, np.linspace(0, 220, len(labels))):
    text = plt.text(position, -0.5, label.split()[0] + ' ', color = color, size = 15, horizontalalignment = 'right')
    text.draw(fig.canvas.get_renderer())
    ex = text.get_window_extent()
    transforms.offset_copy(text._transform, y = ex.height, units = 'dots')
    text = plt.text(position + 2, -0.5, label.split()[1], color = 'black', size = 10, horizontalalignment = 'left')
    text.draw(fig.canvas.get_renderer())
    ex = text.get_window_extent()
    transforms.offset_copy(text._transform, y = ex.height, units = 'dots')

在这种情况下你必须优化:

  • 图形大小(figsize = (10, 2)
  • 图例总长度(np.linspace(0, 220, len(labels))
  • space 文本之间 (position + 2)
  • 文字大小(size = 15

根据您的需要。