为什么要用子图
为了能同时展示多个图表、便于图表之间数据的直观对比和分析,更高效地组织复杂的可视化信息,通常会在一个画布上创建多个子图。
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) |
| 折线图 / 柱状图 / 饼状图分别适合什么? | 趋势变化 / 数量对比 / 比例构成 |
相关
练习题
一、知识回顾(读完直接做下面的实践题)
- 创建子图:
figure, axes = plt.subplots(nrows=2, ncols=2, figsize=(20, 12), dpi=100) figure是画布对象,axes是子图数组- 一行两列时子图是
axes[0]、axes[1];两行两列时是axes[行][列]的形式 - 折线图用
plot,柱状图用bar,饼图用pie - 折线图适合展示趋势变化,柱状图适合展示数量对比,饼图适合展示比例构成
- 子图上设置标题用
axes.set_title('...')(比全局写法多一个set_) - 饼图显示百分比用参数
autopct='%1.1f%%' - 保存图片用
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)- 参考答案(做完再点开)
pythonimport 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)
