Matplotlib 带状箱形图

Beginner

This tutorial is from open-source community. Access the source code

简介

Matplotlib 是一个广受欢迎的用于 Python 的数据可视化库。本教程将指导你创建一个带状箱形图,这是一种可视化数据的独特方式。带状箱形图是一种堆叠条形图,其中每个条形都是“带状”的,并且具有渐变配色方案。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。

导入库并加载数据

在这一步中,我们将导入必要的库并加载数据。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cbook
from matplotlib import colors as mcolors
from matplotlib.image import AxesImage
from matplotlib.transforms import Bbox, BboxTransformTo, TransformedBbox

创建 RibbonBox 类

在这一步中,我们将创建 RibbonBox 类,该类将用于为带状箱形图创建渐变颜色。

class RibbonBox:
    ## 加载带状箱形图图像
    original_image = plt.imread(cbook.get_sample_data("Minduka_Present_Blue_Pack.png"))
    cut_location = 70
    b_and_h = original_image[:, :, 2:3]
    color = original_image[:, :, 2:3] - original_image[:, :, 0:1]
    alpha = original_image[:, :, 3:4]
    nx = original_image.shape[1]

    def __init__(self, color):
        rgb = mcolors.to_rgb(color)
        self.im = np.dstack([self.b_and_h - self.color * (1 - np.array(rgb)), self.alpha])

    def get_stretched_image(self, stretch_factor):
        stretch_factor = max(stretch_factor, 1)
        ny, nx, nch = self.im.shape
        ny2 = int(ny*stretch_factor)
        return np.vstack([self.im[:self.cut_location],
                          np.broadcast_to(self.im[self.cut_location], (ny2 - ny, nx, nch)),
                          self.im[self.cut_location:]])

创建 RibbonBoxImage 类

在这一步中,我们将创建 RibbonBoxImage 类,该类将用于创建实际的带状箱形图。

class RibbonBoxImage(AxesImage):
    zorder = 1

    def __init__(self, ax, bbox, color, *, extent=(0, 1, 0, 1), **kwargs):
        super().__init__(ax, extent=extent, **kwargs)
        self._bbox = bbox
        self._ribbonbox = RibbonBox(color)
        self.set_transform(BboxTransformTo(bbox))

    def draw(self, renderer, *args, **kwargs):
        stretch_factor = self._bbox.height / self._bbox.width

        ny = int(stretch_factor*self._ribbonbox.nx)
        if self.get_array() is None or self.get_array().shape[0]!= ny:
            arr = self._ribbonbox.get_stretched_image(stretch_factor)
            self.set_array(arr)

        super().draw(renderer, *args, **kwargs)

创建图表

在这一步中,我们将通过使用 RibbonBoxImage 类来创建带状箱形图,从而创建实际的图表。

def main():
    fig, ax = plt.subplots()

    years = np.arange(2004, 2009)
    heights = [7900, 8100, 7900, 6900, 2800]
    box_colors = [(0.8, 0.2, 0.2),
                  (0.2, 0.8, 0.2),
                  (0.2, 0.2, 0.8),
                  (0.7, 0.5, 0.8),
                  (0.3, 0.8, 0.7)]

    for year, h, bc in zip(years, heights, box_colors):
        bbox0 = Bbox.from_extents(year - 0.4, 0., year + 0.4, h)
        bbox = TransformedBbox(bbox0, ax.transData)
        ax.add_artist(RibbonBoxImage(ax, bbox, bc, interpolation="bicubic"))
        ax.annotate(str(h), (year, h), va="bottom", ha="center")

    ax.set_xlim(years[0] - 0.5, years[-1] + 0.5)
    ax.set_ylim(0, 10000)

    ## 创建背景渐变
    background_gradient = np.zeros((2, 2, 4))
    background_gradient[:, :, :3] = [1, 1, 0]
    background_gradient[:, :, 3] = [[0.1, 0.3], [0.3, 0.5]]
    ax.imshow(background_gradient, interpolation="bicubic", zorder=0.1,
              extent=(0, 1, 0, 1), transform=ax.transAxes, aspect="auto")

    plt.show()

main()

理解图表

在这一步中,我们将讨论我们创建的图表。该图表由相互堆叠的带状箱形图组成,形成了一个柱状图。每个带状箱形图的高度对应于数据集中的一个值。带状箱形图具有渐变配色方案,使其在视觉上更具吸引力。

总结

在本教程中,我们学习了如何使用 Matplotlib 创建一个带状箱形图。我们分别创建了 RibbonBoxRibbonBoxImage 类来创建渐变颜色和实际的带状箱形图。然后,我们使用这些类来创建图表,该图表由相互堆叠的带状箱形图组成,形成一个柱状图。