Skip to content

为什么要用子图 ​

为了能同时展示多个图表、便于图表之间数据的直观对比和分析,更高效地组织复杂的可视化信息,通常会在一个画布上创建多个子图。

python
import matplotlib.pyplot as plt

figure, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 6), dpi=100)
# figure : 画布对象
# axes   : 子图数组(里面装着 Axes 对象)
# nrows / ncols : 行数 / 列数     figsize : 画布大小     dpi : 清晰度

axes[0].bar(...)   # 左边的子图:柱状图
axes[1].pie(...)   # 右边的子图:饼状图

axes 的索引规则 ​

布局取值方式
nrows=1, ncols=2(一行两列)axes[0]、axes[1]
nrows=2, ncols=2(两行两列)axes[0][0]、axes[0][1]、axes[1][0]、axes[1][1](axes[行][列])

TIP

记住 axes[行][列] 就能定位任意子图;写成 axes1 = axes[0][0] 这样起个短名字,后面设置标题就不用重复写下标了。

三种常用图表 ​

图表方法适用场景
折线图plot(x, y)展示趋势变化(如每年电影数量)
柱状图bar(x, y, width=0.6, color='g')展示数量对比(如各国石油储备)
饼图pie(values, labels=..., autopct='%1.1f%%')展示比例构成(如各国人口占比)

子图上的设置 ​

在外面用 plt.xxx,在子图上就用 axes.xxx(多一个 set_):

全局写法子图写法
plt.title('...')axes.set_title('...', fontsize=18)
plt.xlabel('...')axes.set_xlabel('...')
plt.ylabel('...')axes.set_ylabel('...')
plt.grid(...)axes.grid(...)

完整示例:柱状图 + 饼图 ​

python
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

figure, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 6), dpi=100)

# 图一:柱状图(世界石油储备)
countries = ['中国', '美国', '印度', '加拿大', '伊拉克', '沙特', '伊朗', '英国', '德国']
values = [35, 23, 18, 21, 56, 78, 51, 12, 18]

axes[0].bar(countries, values, width=0.6, color='g')
axes[0].set_title('世界石油储备', fontsize=18)
axes[0].set_xlabel('国家')
axes[0].set_ylabel('石油储备(亿吨)')
axes[0].grid(linestyle='--', alpha=0.3)

# 图二:饼状图(世界人口比例)
countries2 = ['印度', '中国', '美国', '印尼', '巴基斯坦', '其他']
values2 = [14.51, 14.09, 3.4, 2.83, 2.51, 20]

axes[1].pie(values2, labels=countries2, autopct='%1.1f%%')
axes[1].set_title('世界人口比例', fontsize=18)
axes[1].legend(loc='lower center', ncol=3, bbox_to_anchor=(0.5, -0.08))

plt.savefig('data/01.png')   # 保存图片
plt.show()                   # 展示图表
参数作用
autopct='%1.1f%%'饼图上显示百分比(保留 1 位小数)
legend(ncol=3, bbox_to_anchor=(0.5, -0.08))ncol 每行显示几个图例;bbox_to_anchor 控制图例位置
tick_params(axis='x', rotation=90)X 轴标签旋转 90 度(标签太长时用)

小结(复习自测) ​

题目答案
如何在画布中创建子图?figure, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 6), dpi=100)
折线图 / 柱状图 / 饼状图分别适合什么?趋势变化 / 数量对比 / 比例构成

相关 ​

练习题 ​

一、知识回顾(读完直接做下面的实践题) ​

  1. 创建子图:figure, axes = plt.subplots(nrows=2, ncols=2, figsize=(20, 12), dpi=100)
  2. figure 是画布对象,axes 是子图数组
  3. 一行两列时子图是 axes[0]、axes[1];两行两列时是 axes[行][列] 的形式
  4. 折线图用 plot,柱状图用 bar,饼图用 pie
  5. 折线图适合展示趋势变化,柱状图适合展示数量对比,饼图适合展示比例构成
  6. 子图上设置标题用 axes.set_title('...')(比全局写法多一个 set_)
  7. 饼图显示百分比用参数 autopct='%1.1f%%'
  8. 保存图片用 plt.savefig('data/01.png')

二、裸写题 ​

  • - 提示(先自己想,实在想不出再点开)

    一级 · 思路:先建子图拿到 axes,再往 axes[0]、axes[1] 上分别画 二级 · 方法:plt.subplots(nrows=1, ncols=2, figsize=(20, 6)) / axes[0].bar(...) / axes[1].pie(...)三级 · 骨架:axes[0].set_title('...', fontsize=18)

    - 参考答案(做完再点开)

    python
    import matplotlib.pyplot as plt
    
    plt.rcParams['font.sans-serif'] = ['SimHei']
    
    cities = ['北京', '上海', '广州', '深圳', '成都']
    pops = [2184, 2487, 1868, 1756, 2126]
    
    # 2-1
    fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 6), dpi=100)
    axes[0].bar(cities, pops, width=0.6, color='g')
    axes[0].set_title('城市人口对比', fontsize=18)
    axes[0].set_xlabel('城市')
    axes[0].set_ylabel('人口(万)')
    
    axes[1].pie(pops, labels=cities, autopct='%1.1f%%')
    axes[1].set_title('城市人口占比', fontsize=18)
    plt.show()
  • - 提示(先自己想,实在想不出再点开)

    一级 · 思路:画布标题是 fig 级别的,不是某个子图的 二级 · 方法:fig.suptitle('总标题', x=0.5, y=0.95) / fig.subplots_adjust(hspace=0.4, wspace=0.2)三级 · 骨架:fig, axes = plt.subplots(nrows=2, ncols=2);左上角是 axes[____][____],右下角是 axes[____][____]

    - 参考答案(做完再点开)

    python
    # 2-2 两行两列 + 画布标题
    fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(20, 12), dpi=100)
    fig.suptitle('城市人口分析', fontsize=23, x=0.5, y=0.95)
    fig.subplots_adjust(hspace=0.4, wspace=0.2)
    
    axes[0][0].bar(cities, pops, color='g')
    axes[0][0].set_title('人口对比', fontsize=15)
    
    axes[1][1].pie(pops, labels=cities, autopct='%1.1f%%')
    axes[1][1].set_title('人口占比', fontsize=15)
    plt.show()
  • - 提示(先自己想,实在想不出再点开)

    一级 · 思路:旋转刻度标签 二级 · 方法:axes.tick_params(axis='x', rotation=90)三级 · 骨架:axis='____' 指定是哪根轴

    - 参考答案(做完再点开)

    python
    # 2-3:接在 2-2 的柱状图后面,让 X 轴标签竖排
    axes[0][0].tick_params(axis='x', rotation=90)