Matplotlib 是专门用于开发2D图表(包括3D图表——较少)的库,其使用方式简单,以渐进、交互式的方法实现数据的可视化
可视化是在整个数据挖掘的关键辅助工具,可以用更清晰的方式来展现数据,帮助我们理解数据,从而调整我们的分析方法
但是 Matplotlib 主要以绘制2D图表为主,而一些更为炫酷的图表和3D图表 Matplotlib 是无能为力的,但除了 Matplotlib 之外还有其他许多更多的库,如:百度的 Echarts 库,更详细的扩展内容可以浏览以下网址:
对于我们日常的数据挖掘与数据分析来说, Matplotlib 就已经足够了,毕竟是给自己看的,不需要太炫酷
(1)容器层——底层:
主要由 Canvas(画板)、Figure(画布、图片)、Axes(图表)组成
图像层指 图表Axes 内通过 折线图plot、散点图scatter、柱状图bar、轮廓图contour、直方图hist、barbs、饼图pie 等函数根据数据绘制出的图像
(3)辅助显示层——位于图表Axes上:
辅助显示层为 图表Axes 内除了根据数据绘制出的图像以为的内容,主要包括:外观facecolor、网格线grid、图例legend、标体title、坐标轴axis 等内容,该层的设置可使图像显示得更为直观而易于被人理解,但又不会对图像产生实质的影响,如:坐标轴示数、标题等
折线图 plot:能够显示数据的变化趋势,反映事物的变化情况(变化)
散点图 scatter:判断变量之间是否存在数量关联趋势,展示离群点(分布规律)
柱状图 bar:绘制成离散的数据,能够一眼看出各个数据的大小,比较数据之间的差别(统计/对比)
直方图 hist:由一系列高度不等的纵向柱段表示数据的分布情况,一般横轴表示数据范围,纵轴表示某一范围的数量情况,绘制连续性的数据展示一组或者多组数据的分布状况(统计)
饼图 pie:分类数据的占比情况(占比)
柱状图与直方图的区别:
matplotlib.pyplot 模块包含了一系列类似于MATLAB的画图函数,它的函数作用于当前 画布Figure 的当前坐标系 图表Axes
导入模块并命名为 plt
import matplotlib.pyplot as plt
plt.figure()
创建画布
plt.savefig(PATH)
可以保存绘制出的图像
PATH 可以是相对路径或绝对路径
当路径为相对路径时,当前工作目录为在Jupyter Notebook 中 New .ipynb 文件的位置plt.show()
显示图像
plt.figure()
以默认的属性创建画布
plt.figure(figsize=(width, height), dpi=)
指定画布的属性创建画布
figsize=() 指定图的宽和高
dpi= 指定图像的清晰度
返回值 fig 对象plt.plot(点系x轴列表, 点系y轴列表)
绘制折线图
plt.show()
显示图像
例:展现上海一周的天气,比如从星期一到星期日的天气温度如下
import matplotlib.pyplot as plt
plt.figure()
plt.plot([1, 2, 3, 4, 5, 6, 7], [16, 19, 14, 15, 11, 11, 9])
# 保存文件
plt.savefig("C://Users/GOODman/Desktop/")
plt.show()
import matplotlib.pyplot as plt
plt.figure(figsize=(20, 8), dpi=80)
plt.plot([1, 2, 3, 4, 5, 6, 7], [16, 19, 14, 15, 11, 11, 9])
plt.show()
plt.xticks(x, [labels], [**kwargs])
指定x轴的刻度,括号 () 内不指定内容时取默认刻度
x 刻度,相当于是指定x轴上的刻度,必须是由数字组成的列表,其中在该列表指定了的数字就是将会显示的刻度值
- 刻度是一直存在的,而x标签则指定了其对应位置的刻度是否显示出来(重要)
plt.yticks(y, [labels], [**kwargs])
指定y轴的刻度,括号 () 内不指定内容时取默认刻度
y 刻度,相当于是指定y轴上的刻度,必须是由数字组成的列表,其中在该列表指定了的数字就是将会显示的刻度值
- 刻度是一直存在的,而x标签则指定了其对应位置的刻度是否显示出来(重要)
注:x/y 和 labels标签 是两个一 一对应的列表,因此它们的长度要设置为相等,否则会报错
例:上海某地区某一个小时内每分钟的温度变化波动范围在15~18℃之内
设置从0开始且步长为5的的刻度坐标轴——两种方法(重要)
import matplotlib.pyplot as plt
import random
"""生成[0, 1, 2,..., 58, 59]的列表"""
x = range(60)
"""生成包含60个元素的列表,这些元素是[15, 18]之间的随机数"""
y = [random.uniform(15, 18) for i in x]
plt.figure(figsize=(20, 8), dpi=200)
plt.plot(x, y)
"""使用列表切片的方式设置步长为5"""
plt.xticks(x[::5])
"""使用range()函数设置步长"""
plt.yticks(range(0, 25, 5))
plt.show()
例:修改刻度的值为 11:00 的时间格式 ,蓝色字体,倾斜角为 30°,步长为5分
import matplotlib.pyplot as plt
import random
"""数据准备"""
x = range(60)
y = [random.uniform(15, 18) for i in x]
"""创建画布"""
plt.figure(figsize=(10, 8), dpi=80)
""""绘制折线图"""
plt.plot(x, y)
"""修改x轴刻度"""
x_labels = ["11时{:02d}分".format(i) for i in x]
plt.xticks(x[::5], x_labels[::5], color="blue", rotation=30)
plt.yticks(range(0, 25, 5))
plt.show()
注:在 Jupyter Notebook 中绘图时,刻度值是默认无法显示中文的,可以加上以下几行代码来显示中文:
import matplotlib.pyplot as plt
# 指定默认字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family']='sans-serif'
# 解决负号'-'显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
plt.grid(True, [linestyle="-"], [alpha=1])
可以让图表显示网格
True 表示显示网格
linestyle="-" 表示网格线的风格,默认为实线
alpha=1 表示网格线的透明度,默认值为1
例:
import matplotlib.pyplot as plt
import random
plt.figure(figsize=(5, 4), dpi=80)
plt.grid(True, linestyle="-", alpha=0.6)
plt.show()
描述信息即 x/y 的数值所代表的含义
plt.xlabel(字符串)
为x轴添加 字符串 标签
plt.ylabel(字符串)
为y轴添加 字符串 标签
plt.title(字符串)
为图表添加 字符串 标签标体
例:
import matplotlib.pyplot as plt
import random
plt.figure(figsize=(5, 4), dpi=80)
plt.grid(True, linestyle="-", alpha=0.6)
plt.xlabel("时间")
plt.ylabel("温度")
plt.title("中午11时00分到11时55分之间的温度变化")
plt.show()
再次调用 plt.plot(点系x轴列表, 点系y轴列表) 函数即可添加多条折线
例:增加北京某地区某一个小时内每分钟的温度变化波动范围在-10~4℃之内
import matplotlib.pyplot as plt
import random
x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]
y_beijing = [random.uniform(-10, 4) for i in x]
plt.figure(figsize=(10, 8), dpi=80)
plt.plot(x, y_shanghai)
plt.plot(x, y_beijing)
x_labels = ["11时{:02d}分".format(i) for i in x]
plt.xticks(x[::5], x_labels[::5], color="blue", rotation=30)
plt.yticks(range(-10, 25, 5))
"""显示网格"""
plt.grid(True, linestyle="-", alpha=0.6)
plt.xlabel("时间")
plt.ylabel("温度")
plt.title("上海、北京某地区在某个小时内的温度变化")
plt.show()
在有多条折线的情况下,折线的风格可能需要指定成更易于区分的风格,可以指定:
plt.plot(点系x轴列表, 点系y轴列表, color="", linestyle="")
指定折线图 的风格
color="" 指定折线的颜色
linetytle="" 指定折线的线条
color | 含义 | linestyle | 含义 |
---|---|---|---|
r | 红色 | - | 实线 |
g | 绿色 | -- | 虚线 |
b | 蓝色 | -. | 点划线 |
w | 白色 | : | 点虚线 |
c | 青色 | 空格 | 留空 |
m | 洋红 | ||
y | 黄色 | ||
k | 黑色 |
在有多条折线的情况下,通常还需要指定折线的标签——折线含义:
(1) 此时就要在 plot() 函数中为当前绘制的折线添加标签
plt.plot(点系x轴列表, 点系y轴列表, label="")
label="" 即为当前绘制的折线添加标签
(2) 添加标签后还需要调用 legend() 函数显示标签
plt.legend(loc="")
把图表所指定的标签显示出来
loc="" 用于指定标签的显示位置
默认时选择最佳位置,一般不用指定loc,取默认值即可
loc | 含义 |
---|---|
“best” 或 0 | 最佳位置(默认值) |
“upper right” 或 1 | 右上方 |
“upper left” 或 2 | 左上方 |
“lower left” 或 3 | 右下方 |
“lower right” 或 4 | 左下方 |
“right” 或 5 | 右端 |
“center left” 或 6 | 左端中部 |
例:
此处仅展示部分关键代码
plt.plot(x, y_shanghai, label="上海")
plt.plot(x, y_beijing, label="北京")
plt.legend()
在前面,我们整个绘图过程相当于面向过程绘图,下面利用面向对象的画图方法来在多个坐标系上显示图表
图对象,列表 = plt.subplots(nrows=1, ncols=1, **fig_kw)
创建一个带有多个Axes图表 坐标系的图
nrows=1 是图像的行显示数
ncols=1 是图像的列显示数
即图表的总个数为 nrows × ncols
返回值 有两个返回值:
- 图对象fig 画布对象
- 图表axes对象列表 可以通过下标值来访问第几个图表
**fig_kw 为图表的格式设置,如:figsize=(10, 8),dpi=80等
发生变化的方法:
在原来的面向过程绘图中 plt.xticks(x, [labels], [**kwargs]) 可以同时传递三个参数,但在面向对象中,该函数发生了分解,分解成为两个方法:
set_xticks(x)
设置x轴的刻度
set_xticklabels(labels, [**kwargs])
如果需要覆盖原刻度值的内容,则需要在这个方法中指定
set_yticks(y)
设置y轴刻度
set_yticklabels(labels, [**kwargs])
如果需要覆盖原刻度值的内容,则需要在这个方法中指定
此外,原指定x轴和y轴标签的 xlabel() 函数和 ylabel() 函数的名称发生变化,指定标题标签的 title() 函数的名称也发生了变化,它们的用法和前面的函数相同,名称多了个 set_
set_xlabel()
设置x轴标签
set_ylabel()
设置y轴标签
set_title()
import matplotlib.pyplot as plt
import random
"""准备x轴和y轴坐标"""
x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]
y_beijing = [random.uniform(-10, 4) for i in x]
"""创建画布和图表"""
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=80)
"""可以绘制多个折线图"""
axes[0].plot(x, y_shanghai, label="上海")
axes[1].plot(x, y_beijing, label="北京")
"""显示图例"""
axes[0].legend()
axes[1].legend()
"""构建x轴的变化刻度"""
x_ticklabels = ["11:{:02d}".format(i) for i in x]
"""修改x轴和y轴的刻度显示"""
axes[0].set_xticks(x[::5])
axes[0].set_xticklabels(x_ticklabels[::5], color="blue", rotation=30)
axes[0].set_yticks(range(-10, 25, 5))
axes[1].set_xticks(x[::5])
axes[1].set_xticklabels(x_ticklabels[::5], color="blue", rotation=30)
axes[1].set_yticks(range(-10, 25, 5))
"""添加网络显示"""
axes[0].grid(True, linestyle="--", alpha=0.6)
axes[1].grid(True, linestyle="--", alpha=0.6)
"""添加x轴和y轴描述信息和标题"""
axes[0].set_xlabel("时间")
axes[0].set_ylabel("温度")
axes[0].set_title("上海某地区在某个小时内的温度变化")
axes[1].set_xlabel("时间")
axes[1].set_ylabel("温度")
axes[1].set_title("北京某地区在某个小时内的温度变化")
"""显示图像"""
plt.show()
折线图能够很好地反映因变量随自变量的波动变化规律,在股市中尤为明显
此外,plt.plot() 除了可以画折线图,也可以用于画各种属性函数图像
例:此处只是展示效果,不用纠结代码,以后会讲到
import matplotlib.pyplot as plt
import numpy as np
"""准备数据"""
x = np.linspace(-10, 10, 100)
y = np.sin(x)
"""创建画布"""
plt.figure(figsize=(10, 8), dpi=80)
"""绘制函数图像"""
plt.plot(x, y)
"""添加网络表示"""
plt.grid()
"""显示图像"""
plt.show()
由于散点图的特性,我们只关心其变量之间是否存在数量关联趋势,并展示离群点,因此并不需要很多花哨的显示
需求:探究房屋面积和房屋价格的关系
房屋面积数据:
x = [225.98, 247.07, 253.14, 457.85, 241.58, 301.01, 20.67, 288.64, 163.56, 120.06, 207.83, 342, 75, 147.9, 53.06, 224.72, 29.51, 21.61, 483.21, 245.25, 399.25, 343.35]
房屋价格数据:
y = [196.63, 203.88, 210.75, 372.74, 202.41, 247.61, 24.9, 239.34, 140.32, 104.15, 176.84, 288.23, 128.79, 49.64, 191.74, 33.1, 30.74, 400.02, 205.32, 330.64, 283.45]
plt.scatter(点系x轴列表, 点系y轴列表)
绘制散点图
import matplotlib.pyplot as plt
"""准备数据"""
x = [225.98, 247.07, 253.14, 457.85, 241.58, 301.01, 20.67, 288.64,
163.56, 120.06, 207.83, 342.75, 147.9, 53.06, 224.72, 29.51,
21.61, 483.21, 245.25, 399.25, 343.35]
y = [196.63, 203.88, 210.75, 372.74, 202.41, 247.61, 24.9, 239.34,
140.32, 104.15, 176.84, 288.23, 128.79, 49.64, 191.74, 33.1,
30.74, 400.02, 205.32, 330.64, 283.45]
"""创建画布"""
plt.figure(figsize=(10, 8), dpi=80)
"""绘制散点图"""
plt.scatter(x, y)
"""显示图像"""
plt.show()
plt.bar(x, y, [width, align=‘center’, **kwargs])
x 横坐标的数据列表
width 柱状图的宽度
align 指定柱段的位置
- center 柱段在x轴的中间位置,为默认值
- edge 柱段以x轴左对齐
**kwargs 是要指定的属性列表,如:color=[“r”, “g”…“b”] 指定柱状图各柱段的颜色
例:对比下列电影的票房收入
电影名称:
movie_names = ["唐人街探案3", "你好,李焕英", "刺杀小说家", "熊出没·狂野大陆", "新神榜:哪吒重生", "侍神令", "人潮汹涌", "我为你喝彩", "梦醒黄金城"]
对应的票房数(单位:亿):
tickets = [35.65, 27.30, 5.38, 4.06, 2.40, 2.10, 1.50, 0.0271, 0.00039]
import matplotlib.pyplot as plt
"""解决中文显示问题"""
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family']='sans-serif'
plt.rcParams['axes.unicode_minus'] = False
"""准备数据"""
movie_names = ["唐人街探案3", "你好,李焕英", "刺杀小说家", "熊出没·狂野大陆",
"新神榜:哪吒重生", "侍神令", "人潮汹涌", "我为你喝彩", "梦醒黄金城"]
tickets = [35.65, 27.30, 5.38, 4.06, 2.40, 2.10, 1.50, 0.0271, 0.00039]
x = range(len(movie_names))
"""创建画布"""
plt.figure(figsize=(15, 8), dpi=100)
"""绘制柱状图"""
plt.bar(x, tickets, color=["b", "g", "b", "g", "b", "g", "b", "g", "b"])
"""修改刻度值"""
plt.xticks(x, movie_names)
"""添加标签"""
plt.xlabel("电影名称")
plt.ylabel("票房数(单位:亿)")
plt.title("2021年春节档电影截至2021年2月17日票房收入")
"""添加网格显示"""
plt.grid(linestyle="--", alpha=0.6)
"""显示图像"""
plt.show()
上述案例显示了 2021年春节档电影截至2021年2月17日的票房总收入,但有时候电影的上映时间不尽相同,为了柱状图更有说服力,我们需要为每部电影增加一段首映日的票房收入数据,大大增加数据的说服力
思路:绘制多段柱状图的原理,是调用 plt.bar() 绘制两类柱状图之后,并指定柱段的宽度 width,再对其中一类的柱状图所在的位置平移柱段宽度 width 的距离——对 plt.bar() 中的x值进行操作来实现平移
比如说,我们设置第一类柱段的位置分别位于刻度 1、2、3、… n 上,柱段宽度均为 width=0.2,如果我们以相同的刻度位置绘制第二类柱段,那么第一类柱段就会被第二类柱段覆盖。但如果我们使第二类柱段稍微向右平移第一类柱段宽度 width 的距离,使第二类柱段位于刻度 1+width、2+width、3+width、… n+width的位置上,即位于刻度 1.2、2.2、3.2、… n+0.2的位置上,那么两类柱子就会贴合在一起,且互不遮挡,即可实现多类柱状图
当然,刻度覆盖内容的位置要位于两栋柱段的中央位置,因此刻度的标签的位置应该位于刻度
例:对比下列电影的票房收入
电影名称:
movie_names = ["唐人街探案3", "你好,李焕英", "刺杀小说家", "熊出没·狂野大陆", "新神榜:哪吒重生", "侍神令", "人潮汹涌"]
对应的票房数(单位:亿):
total_tickets = [35.65, 27.30, 5.38, 4.06, 2.40, 2.10, 1.50]
首映票房数(单位:亿):
firstday_tickets = [10.06, 2.90, 1.37, 0.7227, 0.5103, 0.8077, 0.4309]
对应的票房数 和 首映票房数 分别是两类柱段
import matplotlib.pyplot as plt
"""解决中文显示问题"""
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family']='sans-serif'
plt.rcParams['axes.unicode_minus'] = False
"""准备数据"""
movie_names = ["唐人街探案3", "你好,李焕英", "刺杀小说家", "熊出没·狂野大陆", "新神榜:哪吒重生", "侍神令", "人潮汹涌"]
total_tickets = [35.65, 27.30, 5.38, 4.06, 2.40, 2.10, 1.50]
firstday_tickets = [10.06, 2.90, 1.37, 0.7227, 0.5103, 0.8077, 0.4309]
"""第一类柱段位置"""
x_movie_names = range(len(movie_names))
"""第二类柱段位置"""
x_total_tickets = [i + 0.2 for i in x_movie_names]
"""刻度位置"""
x_ticks = [i + 0.1 for i in x_movie_names]
"""绘制画布"""
plt.figure(figsize=(12, 8), dpi=100)
"""绘制柱状图"""
plt.bar(x_movie_names, total_tickets, width=0.2, label="总票房收入")
plt.bar(x_total_tickets, firstday_tickets, width=0.2, label="首映票房收入")
"""修改刻度"""
plt.xticks(x_ticks, movie_names)
"""显示图例"""
plt.legend()
"""添加信息和标题"""
plt.xlabel("电影名称")
plt.ylabel("票房数(单位:亿)")
plt.title("2021年春节档电影票房收入统计")
"""显示网格"""
plt.grid(linestyle="--", alpha=0.6)
"""显示图像"""
plt.show()
组数:在统计数据时,我们把数据按照不同的范围分成几个组,分成的组的个数称为组数
组距:每一组的包含范围
总范围 = 组数 × 组距
例:从身高范围 [150,180) 来进行分组,组距为 5cm,则分成的组分别为:
[150,155)、[155,160)、[160,165)、[165,170)、[170,175)、[175,180),因此组数为 6 组
plt.hist(x, bins=None, density=None, **kwargs])
x 样本的数据集列表
bins 组数
density=None 是否将数据显示成频率,默认情况下y轴数据显示的是频数而不是频率,当指定 density=True,y轴将会显示成频率
**kwargs 是要指定的属性列表,如:color=[“r”, “g”…“b”] 指定柱状图各柱段的颜色
设置组数 bins:
通常对于数据较少的情况,分为5~12组,数据较多,更换图形显示方式
例:电影时长分布状况
现有多部电影的时长,希望统计出这些电影时长的分布状况,每2min分为一组(即组距distance=2)
数据:
time = [131, 98, 125, 131, 124, 139, 131, 117, 128, 108, 135, 138, 131, 102, 107, 114, 134, 126, 135, 112, 109, 108, 127, 121, 135, 117, 128, 136, 101, 109, 108, 121, 116, 118, 125, 129, 139, 113, 134, 106, 144, 110, 137, 137, 111, 104, 117, 100, 111, 101, 110, 105, 129, 137, 113]
组距:
distanec = 2
组数:
bins = (max(time) - min(time)) // distance
import matplotlib.pyplot as plt
"""解决中文显示问题"""
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family']='sans-serif'
plt.rcParams['axes.unicode_minus'] = False
"""准备数据"""
time = [131, 98, 125, 131, 124, 139, 131, 117, 128, 108, 135, 138, 131, 102, 124, 107,
114, 134, 126, 135, 112, 109, 108, 127, 121, 135, 117, 128, 136, 123, 101, 109,
108, 121, 116, 118, 125, 129, 123, 139, 113, 134, 106, 144, 110, 137, 137, 111,
104, 117, 100, 111, 101, 110, 105, 129, 137, 113, 123]
distance = 2
bins = (max(time) - min(time)) // distance
x = range(min(time), max(time) + distance, distance)
"""创建画布"""
plt.figure(figsize=(10, 8), dpi=100)
"""绘制直方图"""
plt.hist(time, bins)
"""修改刻度"""
plt.xticks(x)
"""显示信息和标题"""
plt.xlabel("电影时长")
plt.ylabel("电影部数")
plt.title("电影时长分布状况")
"""显示网格"""
plt.grid(linestyle="--", alpha=0.6)
"""显示图像"""
plt.show()
plt.pie(x, labels=, autopct=, colors)
x 数量数据
labels 每部分数据对应的名称
autopct 百分比的显示格式,如:autopec="%.2f%%",则显示格式为 0.00%
colors 每部分的颜色,如:color=[“r”, “g”…“b”]
如果显示的饼图不圆,则在显示图像之前加上下面的代码:
# 使饼图保存圆形
plt.axis("equal")
例:显示各电影的票房数占比
电影名称:
movie_names = ["唐人街探案3", "你好,李焕英", "刺杀小说家", "熊出没·狂野大陆", "新神榜:哪吒重生", "侍神令", "人潮汹涌"]
对应的票房数(单位:亿):
tickets = [35.65, 27.30, 5.38, 4.06, 2.40, 2.10, 1.50]
import matplotlib.pyplot as plt
"""解决中文显示问题"""
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family']='sans-serif'
plt.rcParams['axes.unicode_minus'] = False
"""准备数据"""
movie_names = ["唐人街探案3", "你好,李焕英", "刺杀小说家", "熊出没·狂野大陆", "新神榜:哪吒重生", "侍神令", "人潮汹涌"]
tickets = [35.65, 27.30, 5.38, 4.06, 2.40, 2.10, 1.50]
"""创建画布"""
plt.figure(figsize=(10, 8), dpi=100)
"""绘制饼图"""
plt.pie(tickets, labels=movie_names, autopct="%.2f%%")
"""显示图例"""
plt.legend()
"""使饼图保存圆形"""
plt.axis("equal")
"""显示图像"""
plt.show()