Python中使用Matplotlib绘制甜甜圈图表的全面指南

Python中使用Matplotlib绘制甜甜圈图表的全面指南

参考:Donut Chart using Matplotlib in Python

甜甜圈图(Donut Chart)是一种环形图表,它在饼图的基础上在中心留出了一个空白区域,形状类似甜甜圈。这种图表不仅能展示各部分的比例关系,还可以在中心区域添加额外信息。本文将详细介绍如何使用Python的Matplotlib库绘制甜甜圈图,包括基础绘制、自定义样式、添加标签等多个方面。

1. 甜甜圈图的基本概念

甜甜圈图本质上是一种变形的饼图。它保留了饼图展示各部分占比的特点,同时通过中心的空白区域,为整体数据或其他重要信息预留了位置。这种图表特别适合用于展示构成比例,同时又不想完全遮蔽中心区域的场景。

1.1 甜甜圈图的优势

  1. 视觉吸引力:中心的空白区域使得图表更加美观,不像饼图那样显得沉重。
  2. 信息展示:中心区域可以用来展示总计数值或其他关键信息。
  3. 比例清晰:各部分的占比关系依然清晰可见。
  4. 灵活性:可以通过调整内外半径来改变甜甜圈的宽度。

1.2 使用场景

甜甜圈图适用于多种场景,例如:
– 展示公司各部门的预算分配
– 显示一天24小时的时间分配
– 展示调查问卷中多选题的选择比例
– 表示产品销售的市场份额

2. Matplotlib简介

Matplotlib是Python中最流行的绘图库之一,它提供了一套类似MATLAB的绘图API,能够轻松创建各种静态、动态和交互式图表。

2.1 安装Matplotlib

如果你还没有安装Matplotlib,可以使用pip进行安装:

pip install matplotlib

2.2 导入Matplotlib

在Python脚本中,我们通常这样导入Matplotlib:

import matplotlib.pyplot as plt

3. 绘制基础甜甜圈图

让我们从最简单的甜甜圈图开始。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建甜甜圈图
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90, wedgeprops=dict(width=0.3))

# 添加标题
plt.title('Basic Donut Chart - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
sizes 表示各部分的大小
labels 是对应的标签
autopct='%1.1f%%' 用于在每个扇形上显示百分比
startangle=90 设置起始角度为90度
wedgeprops=dict(width=0.3) 设置甜甜圈的宽度为0.3,这是将饼图转变为甜甜圈图的关键

4. 自定义颜色和样式

我们可以通过设置颜色和其他样式参数来美化甜甜圈图。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#ff99cc']

# 创建甜甜圈图
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90, 
       wedgeprops=dict(width=0.4, edgecolor='white'))

# 添加标题
plt.title('Customized Donut Chart - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
– 我们使用自定义的颜色列表 colors
wedgeprops 中添加了 edgecolor='white',给每个扇形添加白色边框
– 调整了甜甜圈的宽度为0.4

5. 添加中心文本

甜甜圈图的一个优势是可以在中心添加文本信息。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建甜甜圈图
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90, wedgeprops=dict(width=0.3))

# 添加中心文本
centre_circle = plt.Circle((0,0),0.70,fc='white')
fig.gca().add_artist(centre_circle)
ax.text(0, 0, 'Total\n100', ha='center', va='center', fontsize=20)

# 添加标题
plt.title('Donut Chart with Center Text - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

这个例子中:
– 我们创建了一个白色的圆形 centre_circle,覆盖在甜甜圈的中心
– 使用 ax.text() 在中心添加文本

6. 突出显示特定扇形

有时我们需要强调某个特定的扇形,可以通过调整该扇形的位置来实现。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']
explode = (0.1, 0, 0, 0, 0)  # 突出第一个扇形

# 创建甜甜圈图
fig, ax = plt.subplots()
ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', startangle=90, 
       wedgeprops=dict(width=0.3))

# 添加标题
plt.title('Donut Chart with Exploded Slice - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
explode 参数用于设置每个扇形的偏移量,这里我们将第一个扇形偏移0.1

7. 添加图例

当标签较多或较长时,直接在扇形上显示可能会显得拥挤,这时可以使用图例。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['Category A', 'Category B', 'Category C', 'Category D', 'Category E']

# 创建甜甜圈图
fig, ax = plt.subplots()
wedges, texts, autotexts = ax.pie(sizes, labels=labels, autopct='%1.1f%%', 
                                  startangle=90, wedgeprops=dict(width=0.3))

# 添加图例
ax.legend(wedges, labels, title="Categories", loc="center left", bbox_to_anchor=(1, 0, 0.5, 1))

# 添加标题
plt.title('Donut Chart with Legend - how2matplotlib.com')

# 调整布局
plt.tight_layout()

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

这个例子中:
– 我们使用 ax.legend() 添加图例
bbox_to_anchor=(1, 0, 0.5, 1) 用于调整图例的位置

8. 嵌套甜甜圈图

嵌套甜甜圈图可以用来展示层级数据。

import matplotlib.pyplot as plt
import numpy as np

# 数据
size_a = [20, 30, 50]
size_b = [15, 25, 35, 25]
labels_a = ['A1', 'A2', 'A3']
labels_b = ['B1', 'B2', 'B3', 'B4']

# 颜色
colors_a = plt.cm.Reds(np.linspace(0.4, 0.8, 3))
colors_b = plt.cm.Blues(np.linspace(0.4, 0.8, 4))

# 创建图表
fig, ax = plt.subplots()

# 绘制外层甜甜圈
ax.pie(size_a, labels=labels_a, colors=colors_a, radius=1, wedgeprops=dict(width=0.3, edgecolor='white'))

# 绘制内层甜甜圈
ax.pie(size_b, labels=labels_b, colors=colors_b, radius=0.7, wedgeprops=dict(width=0.3, edgecolor='white'))

# 添加标题
plt.title('Nested Donut Chart - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
– 我们使用两个 pie() 调用来创建两个甜甜圈
– 外层甜甜圈的半径为1,内层为0.7
– 使用 plt.cm.Redsplt.cm.Blues 来生成渐变色

9. 动态甜甜圈图

我们可以创建一个动态的甜甜圈图,展示数据随时间的变化。

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

# 初始数据
data = [30, 25, 20, 15, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#ff99cc']

# 创建图表
fig, ax = plt.subplots()

def update(frame):
    # 更新数据
    new_data = [d + np.random.randint(-5, 6) for d in data]
    ax.clear()
    wedges, texts, autotexts = ax.pie(new_data, colors=colors, autopct='%1.1f%%', 
                                      startangle=90, wedgeprops=dict(width=0.3))
    ax.set_title(f'Dynamic Donut Chart - Frame {frame} - how2matplotlib.com')

# 创建动画
ani = animation.FuncAnimation(fig, update, frames=50, interval=200, repeat=False)

plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

这个例子中:
– 我们使用 matplotlib.animation.FuncAnimation 创建动画
update 函数在每一帧更新数据并重新绘制甜甜圈图
– 动画包含50帧,每帧间隔200毫秒

10. 半甜甜圈图

有时我们可能需要绘制半甜甜圈图,这可以通过设置起始和结束角度来实现。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建半甜甜圈图
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90, 
       wedgeprops=dict(width=0.3), counterclock=False)

# 设置y轴限制使其成为半圆
ax.set_ylim(-1.1, 1.1)

# 添加标题
plt.title('Half Donut Chart - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
– 我们使用 counterclock=False 来设置顺时针方向
– 通过 ax.set_ylim(-1.1, 1.1) 限制y轴范围,使图表变成半圆形

11. 带有子图的甜甜圈图

我们可以在一个图表中绘制多个甜甜圈图,以便进行比较。

import matplotlib.pyplot as plt

# 数据
data1 = [30, 20, 25, 15, 10]
data2 = [25, 25, 20, 20, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建带有子图的图表
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

# 绘制第一个甜甜圈图
ax1.pie(data1, labels=labels, autopct='%1.1f%%', startangle=90, wedgeprops=dict(width=0.3))
ax1.set_title('Donut Chart 1 - how2matplotlib.com')

# 绘制第二个甜甜圈图
ax2.pie(data2, labels=labels, autopct='%1.1f%%', startangle=90, wedgeprops=dict(width=0.3))
ax2.set_title('Donut Chart 2 - how2matplotlib.com')

# 调整布局
plt.tight_layout()

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

这个例子中:
– 我们使用 plt.subplots(1, 2) 创建一个包含两个子图的图表
– 在每个子图上分别绘制一个甜甜圈图

12. 带有阴影的甜甜圈图

添加阴影可以增加甜甜圈图的立体感。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建带阴影的甜甜圈图
fig, ax = plt.subplots()
wedges, texts, autotexts = ax.pie(sizes, labels=labels, autopct='%1.1f%%', 
                                  startangle=90, wedgeprops=dict(width=0.3),
                                  shadow=True)

# 添加标题
plt.title('Donut Chart with Shadow - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
– 我们添加了 shadow=True 参数来为甜甜圈图添加阴影效果

13. 带有渐变色的甜甜圈图

使用渐变色可以使甜甜圈图更加美观和有层次感。

import matplotlib.pyplot as plt
import numpy as np

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建渐变色
colors = plt.cm.viridis(np.linspace(0, 1, len(sizes)))

# 创建带渐变色的甜甜圈图
fig, ax = plt.subplots()
wedges, texts, autotexts = ax.pie(sizes, labels=labels, autopct='%1.1f%%', 
                                  startangle=90, wedgeprops=dict(width=0.3),
                                  colors=colors)

# 添加标题
plt.title('Donut Chart with Gradient Colors - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

这个例子中:
– 我们使用 plt.cm.viridis 颜色映射和 np.linspace 来创建渐变色
– 通过 colors 参数将渐变色应用到甜甜圈图中

14. 带有图像纹理的甜甜圈图

我们可以使用图像作为甜甜圈图的纹理,使其更加独特。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle, Wedge
from matplotlib.collections import PatchCollection

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建图表
fig, ax = plt.subplots()

# 创建甜甜圈图的各个部分
patches = []
for i, size in enumerate(sizes):
    wedge = Wedge((0, 0), 0.8, i*360/sum(sizes), (i+1)*360/sum(sizes), width=0.3)
    patches.append(wedge)

# 创建纹理图像
texture = np.random.rand(10, 10)
collection = PatchCollection(patches, cmap=plt.cm.viridis, alpha=0.8)
collection.set_array(np.array(sizes))

# 添加甜甜圈图到坐标轴
ax.add_collection(collection)

# 添加标签
for i, label in enumerate(labels):
    angle = (i + 0.5) * 360 / sum(sizes)
    x = 0.9 * np.cos(np.radians(angle))
    y = 0.9 * np.sin(np.radians(angle))
    ax.text(x, y, label, ha='center', va='center')

# 设置坐标轴
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_aspect('equal')
ax.axis('off')

# 添加标题
plt.title('Donut Chart with Texture - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
– 我们使用 Wedge 对象创建甜甜圈图的各个部分
– 使用 np.random.rand 创建随机纹理
– 通过 PatchCollection 将纹理应用到甜甜圈图上

15. 交互式甜甜圈图

使用 Matplotlib 的事件处理功能,我们可以创建一个交互式的甜甜圈图。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建甜甜圈图
fig, ax = plt.subplots()
wedges, texts, autotexts = ax.pie(sizes, labels=labels, autopct='%1.1f%%', 
                                  startangle=90, wedgeprops=dict(width=0.3))

# 添加标题
plt.title('Interactive Donut Chart - how2matplotlib.com')

# 交互函数
def on_click(event):
    if event.inaxes == ax:
        for wedge in wedges:
            if wedge.contains_point([event.x, event.y]):
                wedge.set_radius(wedge.r + 0.05)
                fig.canvas.draw_idle()
            else:
                wedge.set_radius(1)
                fig.canvas.draw_idle()

# 连接事件
fig.canvas.mpl_connect('button_press_event', on_click)

plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

这个例子中:
– 我们定义了一个 on_click 函数来处理鼠标点击事件
– 当点击某个扇形时,该扇形会稍微突出显示
– 使用 fig.canvas.mpl_connect 将点击事件与处理函数连接起来

16. 带有动态更新的甜甜圈图

我们可以创建一个动态更新的甜甜圈图,模拟实时数据变化。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

# 初始数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建图表
fig, ax = plt.subplots()

def update(frame):
    # 更新数据
    new_sizes = [s + np.random.randint(-5, 6) for s in sizes]
    ax.clear()
    wedges, texts, autotexts = ax.pie(new_sizes, labels=labels, autopct='%1.1f%%', 
                                      startangle=90, wedgeprops=dict(width=0.3))
    ax.set_title(f'Dynamic Updating Donut Chart - Frame {frame} - how2matplotlib.com')

# 创建动画
ani = FuncAnimation(fig, update, frames=50, interval=200, repeat=False)

plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
– 我们使用 FuncAnimation 创建动画
update 函数在每一帧更新数据并重新绘制甜甜圈图
– 动画包含50帧,每帧间隔200毫秒

17. 多层甜甜圈图

多层甜甜圈图可以用来展示更复杂的层级数据。

import matplotlib.pyplot as plt
import numpy as np

# 数据
sizes_outer = [30, 20, 25, 15, 10]
sizes_middle = [15, 25, 35, 25]
sizes_inner = [40, 60]
labels_outer = ['A', 'B', 'C', 'D', 'E']
labels_middle = ['F', 'G', 'H', 'I']
labels_inner = ['J', 'K']

# 颜色
colors_outer = plt.cm.Reds(np.linspace(0.4, 0.8, 5))
colors_middle = plt.cm.Blues(np.linspace(0.4, 0.8, 4))
colors_inner = plt.cm.Greens(np.linspace(0.4, 0.8, 2))

# 创建图表
fig, ax = plt.subplots()

# 绘制外层甜甜圈
ax.pie(sizes_outer, labels=labels_outer, colors=colors_outer, radius=1, 
       wedgeprops=dict(width=0.2, edgecolor='white'))

# 绘制中层甜甜圈
ax.pie(sizes_middle, labels=labels_middle, colors=colors_middle, radius=0.8, 
       wedgeprops=dict(width=0.2, edgecolor='white'))

# 绘制内层甜甜圈
ax.pie(sizes_inner, labels=labels_inner, colors=colors_inner, radius=0.6, 
       wedgeprops=dict(width=0.2, edgecolor='white'))

# 添加标题
plt.title('Multi-layer Donut Chart - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

这个例子中:
– 我们使用三个 pie() 调用来创建三层甜甜圈
– 每层甜甜圈使用不同的半径和颜色

18. 带有数据标签的甜甜圈图

除了百分比,我们还可以在甜甜圈图上显示实际的数据值。

import matplotlib.pyplot as plt

# 数据
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']

# 创建甜甜圈图
fig, ax = plt.subplots()

def make_autopct(values):
    def my_autopct(pct):
        total = sum(values)
        val = int(round(pct*total/100.0))
        return f'{pct:.1f}%\n({val:d})'
    return my_autopct

wedges, texts, autotexts = ax.pie(sizes, labels=labels, 
                                  autopct=make_autopct(sizes),
                                  startangle=90, wedgeprops=dict(width=0.3))

# 添加标题
plt.title('Donut Chart with Data Labels - how2matplotlib.com')

# 显示图表
plt.show()

Output:

Python中使用Matplotlib绘制甜甜圈图表的全面指南

在这个例子中:
– 我们定义了一个 make_autopct 函数来生成自定义的标签格式
– 标签同时显示百分比和实际数值

结论

通过本文的详细介绍和丰富的示例,我们全面探讨了如何使用Python的Matplotlib库绘制各种类型的甜甜圈图。从基础的绘制方法到高级的自定义技巧,这些知识将帮助你创建出既美观又信息丰富的甜甜圈图表。无论是数据可视化、报告制作还是科学研究,甜甜圈图都是一种强大而灵活的工具,能够有效地展示数据中的比例关系和层级结构。希望这篇文章能够为你的数据可视化工作提供有价值的参考和灵感。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程