折线图与柱形图
掌握绘制折线图,绘制柱形图或堆积柱形图。
plot() · bar()
Python 数据可视化 · 第 2 章
从折线图到误差棒图,本章用 10 个绘图函数、10 个实战实例,把一组组枯燥的数字变成一眼可读的图形。
Learning Objectives
本章围绕 10 种基础图表的绘制展开,学习完成后应能独立完成数据到图表的转换。
掌握绘制折线图,绘制柱形图或堆积柱形图。
plot() · bar()
掌握绘制条形图或堆积条形图,绘制堆积面积图、直方图。
barh() · stackplot() · hist()
掌握绘制饼图或圆环图,绘制散点图或气泡图。
pie() · scatter()
掌握绘制箱形图,绘制雷达图,绘制误差棒图。
boxplot() · polar() · errorbar()
Contents
折线图用于展示数据随时间、顺序等连续变量变化的趋势。
使用 pyplot 的 plot() 函数可以快速地绘制折线图。
语法
plot(x, y, fmt, scalex=True, scaley=True, data=None, label=None, *args, **kwargs)
range(len(x))。fmt = '[color][marker][line]'。plot() 函数会返回一个包含 Line2D 类对象(代表线条)的列表。
使用 pyplot 的 plot() 函数还可以绘制具有多个线条的折线图,通过以下任意一种方式均可以完成。
第 1 种
plt.plot(x1, y1) plt.plot(x2, y2)
第 2 种
plt.plot(x1, y1, x2, y2)
第 3 种
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]])
plt.plot(arr[0], arr[1:])
人们每天的生活离不开天气预报,无论是居家还是外出,人们都时刻关注着天气的变化,以便随时备好伞具、增减衣服,或者为后期的出行计划做好准备。本实例要求根据下表的数据,将日期列的数据作为 x 轴数据,将最高气温和最低气温两列的数据作为 y 轴数据,使用 plot() 函数绘制折线图。
表 2-1 北京市未来 15 天的最高气温和最低气温单位:℃
| 日期 | 最高气温 | 最低气温 |
|---|---|---|
| 9 月 4 日 | 32 | 19 |
| 9 月 5 日 | 33 | 19 |
| 9 月 6 日 | 34 | 20 |
| 9 月 7 日 | 34 | 22 |
| 9 月 8 日 | 33 | 22 |
| 9 月 9 日 | 31 | 21 |
| 9 月 10 日 | 30 | 22 |
| 9 月 11 日 | 29 | 16 |
| 9 月 12 日 | 30 | 18 |
| 9 月 13 日 | 29 | 18 |
| 9 月 14 日 | 26 | 17 |
| 9 月 15 日 | 23 | 14 |
| 9 月 16 日 | 21 | 15 |
| 9 月 17 日 | 25 | 16 |
| 9 月 18 日 | 31 | 16 |
图 2-2 未来 15 天最高气温和最低气温折线图(日期为 x 轴,温度 ℃ 为 y 轴)
柱形图以柱形的高度表示数值大小,便于比较不同类别的数量差异。
使用 pyplot 的 bar() 函数可以快速地绘制柱形图或堆积柱形图。
语法
bar(x, height, width=0.8, bottom=None, align='center', tick_label=None, xerr=None, yerr=None, **kwargs)
bar() 函数会返回一个 BarContainer 类的对象。BarContainer 类的对象是一个包含柱形或误差棒的容器,它亦可以视为一个元组,可以遍历获取每个柱形或误差棒;也可以访问 patches 或 errorbar 属性,分别获取图表中所有的柱形或误差棒。
绘制有一组柱形的柱形图
x = np.arange(5) y1 = np.array([10, 8, 7, 11, 13]) # 柱形的宽度 bar_width = 0.3 # 绘制柱形图 plt.bar(x, y1, tick_label=['a','b','c','d','e'], width=bar_width)
绘制有两组柱形的柱形图
x = np.arange(5)
y1 = np.array([10, 8, 7, 11, 13])
y2 = np.array([9, 6, 5, 10, 12])
bar_width = 0.3
plt.bar(x, y1,
tick_label=['a','b','c','d','e'],
width=bar_width)
plt.bar(x+bar_width, y2, width=bar_width)
plt.show()
绘制堆积柱形图
通过给 bar() 函数的 bottom 参数传值,控制柱形的 y 值,使后绘制的柱形位于先绘制的柱形的上方。
# 绘制堆积柱形图
plt.bar(x, y1,
tick_label=['a','b','c','d','e'],
width=bar_width)
plt.bar(x, y2, bottom=y1,
width=bar_width)
绘制有误差棒的柱形图
通过给 xerr、yerr 参数传值的方式,可以为柱形添加误差棒。
# 偏差数据 error = [2, 1, 2.5, 2, 1.5] # 绘制带有误差棒的柱形图 plt.bar(x, y1, tick_label=['a','b','c','d','e'], width=bar_width) plt.bar(x, y1, bottom=y1, width=bar_width, yerr=error)
随着互联网与电子商务的快速发展,人们的消费模式发生了翻天覆地的变化,越来越多的消费者选择网络购物,省时省力。阿里巴巴公司作为中国电商的引领者,其旗下的淘宝和天猫是深受消费者欢迎的网购平台。本实例要求根据下表的数据,将财年列的数据作为 x 轴数据,将 GMV 列的数据作为 y 轴数据,使用 bar() 函数绘制柱形图。
表 2-2 2013—2019 财年淘宝和天猫平台的 GMV单位:亿元
| 财年 | GMV |
|---|---|
| FY2013 | 10770 |
| FY2014 | 16780 |
| FY2015 | 24440 |
| FY2016 | 30920 |
| FY2017 | 37670 |
| FY2018 | 48200 |
| FY2019 | 57270 |
图 2-7 2013—2019 财年 GMV 柱形图(柱形宽度 0.5,x 轴为财年,y 轴为 GMV 亿元)
条形图把类别放在纵轴、数值放在横轴,适合类别名称较长或类别数量较多的场景。
使用 pyplot 的 barh() 函数可以快速地绘制条形图或堆积条形图。
语法
barh(y, width, height=0.8, left=None, align='center', *, **kwargs)
barh() 函数会返回一个 BarContainer 类的对象。
绘制有一组条形的条形图
y = np.arange(5) x1 = np.array([10, 8, 7, 11, 13]) # 条形的高度 bar_height = 0.3 # 绘制条形图 plt.barh(y, x1, tick_label=['a','b','c','d','e'], height=bar_height)
绘制有两组条形的条形图
y = np.arange(5)
x1 = np.array([10, 8, 7, 11, 13])
x2 = np.array([9, 6, 5, 10, 12])
bar_height = 0.3
plt.barh(y, x1,
tick_label=['a','b','c','d','e'],
height=bar_height)
plt.barh(y+bar_height, x2,
height=bar_height)
绘制堆积条形图
通过给 barh() 函数的 left 参数传值,控制条形的 x 值,使后绘制的条形位于先绘制的条形右方。
# 绘制堆积条形图
plt.barh(y, x1,
tick_label=['a','b','c','d','e'],
height=bar_height)
plt.barh(y, x2, left=x1,
height=bar_height)
绘制有误差棒的条形图
通过给 xerr、yerr 参数传值的方式,可以为条形添加误差棒。
# 偏差数据 error = [2, 1, 2.5, 2, 1.5] # 绘制带有误差棒的条形图 plt.barh(y, x1, tick_label=['a','b','c','d','e'], height=bar_height) plt.barh(y, x2, left=x1, height=bar_height, xerr=error)
网络购物已经成为人们日常生活的一部分,它在创造新的消费方式的同时,也在改变着人们的消费模式和习惯,成为拉动居民消费的重要渠道。国家统计局抽取了 771 个样本,并根据这些样本测算用户网购替代率(网购用户线上消费对线下消费的替代比率)的情况。本实例要求根据下表的数据,将商品种类列的数据作为 y 轴的刻度标签,将替代率列的数据作为 x 轴数据,使用 barh() 函数绘制条形图。
表 2-3 各商品种类的网购替代率(部分)
| 商品种类 | 替代率 |
|---|---|
| 家政、家教、保姆等生活服务 | 95.9% |
| 飞机票、火车票 | 95.1% |
| 家具 | 93.5% |
| 手机、手机配件 | 92.4% |
| 计算机及其配套产品 | 89.3% |
| 汽车用品 | 89.2% |
| 通信充值、游戏充值 | 86.5% |
| 个人护理用品 | 86.3% |
| 书报杂志及音像制品 | 86.0% |
下表为部分数据,右侧图表按全部 18 个商品种类绘制。
图 2-9 各商品种类网购替代率条形图(条形高度 0.6,x 轴为网购替代率)
堆积面积图在折线图与 x 轴之间填充颜色,并把多条数据层层堆叠,既看总量也看构成。
使用 pyplot 的 stackplot() 函数可以快速地绘制堆积面积图。
语法
stackplot(x, y, labels=(), baseline='zero', data=None, *args, **kwargs)
绘制有三个填充区域堆叠的堆积面积图
x = np.arange(6)
y1 = np.array([1, 4, 3, 5, 6, 7])
y2 = np.array([1, 3, 4, 2, 7, 6])
y3 = np.array([3, 4, 3, 6, 5, 5])
# 绘制堆积面积图
plt.stackplot(x, y1, y2, y3)
近些年我国物流行业蓬勃发展,目前已经有近几千家物流公司,其中部分物流公司大打价格战,以更低的价格吸引更多的客户,从而抢占市场份额。本实例要求根据下表的数据,将月份列的数据作为 x 轴的刻度标签,将 A 公司、B 公司、C 公司这三列数据作为 y 轴的数据,使用 stackplot() 函数绘制堆积面积图。
表 2-4 A、B、C 物流公司物流费用统计单位:万元
| 月份 | A 公司 | B 公司 | C 公司 |
|---|---|---|---|
| 1 | 198 | 203 | 185 |
| 2 | 215 | 236 | 205 |
| 3 | 245 | 200 | 226 |
| 4 | 222 | 236 | 199 |
| 5 | 200 | 269 | 238 |
| 6 | 236 | 216 | 200 |
| 7 | 201 | 298 | 250 |
| 8 | 253 | 333 | 209 |
| 9 | 236 | 301 | 246 |
| 10 | 200 | 349 | 219 |
| 11 | 266 | 360 | 253 |
| 12 | 290 | 368 | 288 |
图 2-13 A、B、C 公司物流费用堆积面积图(x 轴为月份,y 轴为物流费用 万元)
直方图把连续数据分段(bins)统计频数,用来观察数据的分布形态。
使用 pyplot 的 hist() 函数可以快速地绘制直方图。
语法
hist(x, bins=None, range=None, density=None, weights=None,
bottom=None, **kwargs)
绘制填充的线条直方图
# 准备 50 个随机测试数据 scores = np.random.randint(0, 100, 50) # 绘制直方图 plt.hist(scores, bins=8, histtype='stepfilled')
人脸识别技术是一种生物特征识别技术,它通过从装有摄像头的终端设备拍摄的人脸图像中抽取人的个性化特征,以此来识别人的身份。灰度直方图是实现人脸识别的方法之一,它将数字图像的所有像素按照灰度值的大小统计其出现的频率。本实例要求使用一组 10000 个随机数作为人脸图像的灰度值,使用 hist() 函数绘制灰度直方图。
本实例的绘图代码
import numpy as np import matplotlib.pyplot as plt # 10000 个随机数 random_state = np.random.RandomState(19680801) radom_x = random_state.randn(10000) # 绘制包含 25 个矩形条的直方图 plt.hist(radom_x, bins=25)
随机种子取 19680801,保证每次运行得到相同的分布。
图 2-17 灰度直方图(25 个矩形条,x 轴为灰度值,y 轴为频率)
饼图用扇形的面积表示各部分占总体的比例,圆环图则在中心留出空白。
使用 pyplot 的 pie() 函数可以快速地绘制饼图或圆环图。
语法
pie(x, explode=None, labels=None, autopct=None, pctdistance=0.6,
startangle=None, *, data=None)
wedgeprops={'width': 0.7} 将楔形的宽度设为 0.7。绘制饼图
data = np.array([20, 50, 10, 15, 30, 55])
pie_labels = np.array(['A','B','C','D','E','F'])
# 绘制饼图:半径为 0.5,
# 数值保留 1 位小数
plt.pie(data, radius=1.5,
labels=pie_labels,
autopct='%3.1f%%')
绘制圆环图
data = np.array([20, 50, 10, 15, 30, 55])
pie_labels = np.array(['A','B','C','D','E','F'])
# 绘制圆环图
plt.pie(data, radius=1.5,
wedgeprops={'width': 0.7},
labels=pie_labels,
autopct='%3.1f%%',
pctdistance=0.75)
近年来随着支付 App 的出现,人们的生活发生了翻天覆地的变化,无论是到超市选购商品,还是跟朋友聚餐,或是来一场说走就走的旅行,都可以使用移动支付 App 轻松完成支付,非常便捷。支付宝是人们使用较多的支付方式,它拥有自动记录每月账单的功能,可以方便用户了解每月资金的流动情况。本实例要求根据下表的数据,将分类列的数据作为饼图的标签,将各分类对应的金额与总支出金额的比例作为饼图的数据,使用 pie() 函数绘制饼图。
表 2-5 用户 A 某月使用支付宝的消费明细单位:元
| 分类 | 金额 |
|---|---|
| 购物 | 800 |
| 人情往来 | 100 |
| 餐饮美食 | 1000 |
| 通信物流 | 200 |
| 生活日用 | 300 |
| 交通出行 | 200 |
| 休闲娱乐 | 200 |
| 其他 | 200 |
| 总支出 | 3000 |
图 2-21 支付宝月账单饼图(起始角度 90,离开圆心距离 0.1,显示阴影)
散点图观察两组变量之间的关系,气泡图则用点的大小额外承载一个维度。
使用 pyplot 的 scatter() 函数可以快速地绘制散点图或气泡图。
语法
scatter(x, y, s=None, c=None, marker=None, cmap=None, linewidths=None, edgecolors=None, *, **kwargs)
绘制散点图
num = 50 x = np.random.rand(num) y = np.random.rand(num) plt.scatter(x, y)
绘制气泡图
num = 50 x = np.random.rand(num) y = np.random.rand(num) area = (30 * np.random.rand(num))**2 plt.scatter(x, y, s=area)
汽车的制动距离主要取决于汽车的车速。若车速增加 1 倍,则汽车的制动距离将增大至近 4 倍。某汽车生产公司对一批丰田汽车进行抽样测试,并分别记录了不同的车速对应的制动距离。本实例要求根据下表的数据,将车速(km/h)列的数据作为 x 轴的数据,将制动距离(m)列的数据作为 y 轴的数据,使用 scatter() 函数绘制散点图。
表 2-6 车速与制动距离的关系
| 车速(km/h) | 制动距离(m) | 车速(km/h) | 制动距离(m) |
|---|---|---|---|
| 10 | 0.5 | 110 | 59.5 |
| 20 | 2.0 | 120 | 70.8 |
| 30 | 4.4 | 130 | 83.1 |
| 40 | 7.9 | 140 | 96.4 |
| 50 | 12.3 | 150 | 110.7 |
| 60 | 17.7 | 160 | 126.0 |
| 70 | 24.1 | 170 | 142.2 |
| 80 | 31.5 | 180 | 159.4 |
| 90 | 39.9 | 190 | 177.6 |
| 100 | 49.2 | 200 | 196.8 |
图 2-25 车速与制动距离散点图(x 轴为车速 km/h,y 轴为制动距离 m)
箱形图用四分位数与上下须描述数据的分布,并单独标出异常值。
使用 pyplot 的 boxplot() 函数可以快速地绘制箱形图。
语法
boxplot(x, notch=None, sym=None, vert=None, whis=None, positions=None, widths=None, *, data=None)
绘制不显示异常值的箱形图
data = np.random.randn(100)
plt.boxplot(data, meanline=True,
widths=0.3,
patch_artist=True,
showfliers=False)
本实例要求根据下表的数据,将发电量(亿千瓦时)列的数据作为 x 轴的数据,将 2017 年和 2018 年作为 y 轴的刻度标签,使用 boxplot() 函数绘制箱形图。
表 2-7 2017 年和 2018 年全国发电量统计单位:亿千瓦·时
| 月份 | 2018 年 | 2017 年 |
|---|---|---|
| 1 月 | 5200 | 4605.2 |
| 2 月 | 5254.5 | 4710.3 |
| 3 月 | 5283.4 | 5168.9 |
| 4 月 | 5107.8 | 4767.2 |
| 5 月 | 5443.3 | 4947 |
| 6 月 | 5550.6 | 5203 |
| 7 月 | 6400.2 | 6047.4 |
| 8 月 | 6404.9 | 5945.5 |
| 9 月 | 5483.1 | 5219.6 |
| 10 月 | 5330.2 | 5038.1 |
| 11 月 | 5543 | 5196.3 |
| 12 月 | 6199.9 | 5698.6 |
图 2-29 全国发电量箱形图(箱体宽度 0.5、填充颜色、横向摆放、显示中位数与异常值)
雷达图把多个维度的数值映射到极坐标的各个方向上,便于比较综合特征。
使用 pyplot 的 polar() 函数可以快速地绘制雷达图。
语法
polar(theta, r, **kwargs)
霍兰德职业兴趣测试是由美国职业指导专家霍兰德根据他本人大量的职业咨询经验及其职业类型理论编制的测评工具。根据个人兴趣的不同,霍兰德将人格分为研究型(I)、艺术型(A)、社会型(S)、企业型(E)、传统型(C)和现实型(R)6 个维度,将这 6 个维度不同程度的组合形成每个人的性格。本实例要求根据下表的数据,将标题一行的数据作为雷达图的标签,将其余行的数据作为雷达图的数据,使用 polar() 函数绘制雷达图。
表 2-8 6 名用户霍兰德职业兴趣测试的结果
| 研究型 | 艺术型 | 社会型 | 企业型 | 传统型 | 现实型 | |
|---|---|---|---|---|---|---|
| 用户 1 | 0.40 | 0.32 | 0.35 | 0.30 | 0.30 | 0.88 |
| 用户 2 | 0.85 | 0.35 | 0.30 | 0.40 | 0.40 | 0.30 |
| 用户 3 | 0.43 | 0.89 | 0.30 | 0.28 | 0.22 | 0.30 |
| 用户 4 | 0.30 | 0.25 | 0.48 | 0.85 | 0.45 | 0.40 |
| 用户 5 | 0.20 | 0.38 | 0.87 | 0.45 | 0.32 | 0.28 |
| 用户 6 | 0.34 | 0.31 | 0.38 | 0.40 | 0.92 | 0.28 |
图 2-32 6 名用户的霍兰德职业兴趣雷达图(研究型、艺术型、社会型、企业型、传统型、现实型)
误差棒图在数据点上叠加误差范围,用“数据 ± 偏差”的方式呈现不确定性。
使用 pyplot 的 errorbar() 函数可以快速地绘制误差棒图。
语法
errorbar(x, y, yerr=None, xerr=None, fmt='', ecolor=None, *, data=None, **kwargs)
绘制误差棒图
x = np.arange(5)
y = (25, 32, 34, 20, 25)
y_offset = (3, 5, 2, 3, 3)
plt.errorbar(x, y, yerr=y_offset,
capsize=3, capthick=2)
细根生物量的多少反映了根系从土壤中吸收水分和养分的能力,是植物地下部分集汇能力的重要体现。不同树种细根生物量存在差异性,各树种细根生物量在不同季节间差异较为明显。本实例要求根据下表的数据,将季节列的数据作为 x 轴的刻度标签,将其他列的数据作为 y 轴的数据,使用 errorbar() 函数绘制误差棒图。
表 2-9 4 个树种不同季节的细根生物量单位:g
| 季节 | 马尾松 | 樟树 | 杉木 | 桂花 |
|---|---|---|---|---|
| 春季 | 2.04±0.16 | 1.69±0.27 | 4.65±0.34 | 3.39±0.23 |
| 夏季 | 1.57±0.08 | 1.61±0.14 | 4.99±0.32 | 2.33±0.23 |
| 秋季 | 1.63±0.10 | 1.64±0.14 | 4.94±0.29 | 4.10±0.39 |
图 2-36 4 个树种不同季节细根生物量误差棒图(x 轴为季节,y 轴为细根生物量 g)
Summary
本章主要介绍了如何使用 matplotlib 库的绘图函数绘制简单的图表,包括折线图、柱形图或堆积柱形图、条形图或堆积条形图、堆积面积图、直方图、饼图或圆环图、散点图或气泡图、箱形图、雷达图、误差棒图。通过学习本章的内容,希望大家能够掌握绘图函数的用法,可以使用这些函数绘制简单的图表,为后续的学习打好扎实的基础。