Matplotlib
matplotlib是python的一个数学绘图库,可以很方便的绘制出出版质量级别的图形
功能概述
- 基本绘图
- 绘制曲线
- 设置线型、线宽、颜色
- 设置坐标轴范围及刻度
- 设置坐标轴属性
- 显示图例
- 绘制特殊点
- 添加备注
- 高级图形绘制
- 绘制子图
- 刻度定位器、刻度网格线
- 半对数坐标
- 散点图
- 填充图
- 条形图、饼状图
- 等高线图
- 热成像图
- 极坐标系
- 三俄日曲面
- 简单动画
基本绘图
绘图核心API
import matplotlib.pyplot as mp
# 绘制曲线图 x_array为水平坐标系数组, y_array为垂直坐标系数组
mp.plot(x_array, y_array)
# 绘制垂直线, 给出x坐标, y的最小值和最大值
mp.vlines(x_val, ymin, ymax)
# 绘制水平线, 给出y坐标, x的最小值和最大值
mp.vlines(y_val, xmin, xmax)
绘制水平线和垂直线
# lines.py
import matplotlib.pyplot as mp
import numpy as np
mp.figure('lines')
mp.title('lines')
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.xlim(0, 10)
mp.ylim(0, 10)
mp.tick_params(labelsize=10)
mp.vlines(5, 3, 6, colors='dodgerblue')
mp.hlines(5, 3, 6, colors='orangered')
mp.show()
绘制正弦和余弦曲线
# plt1.py
import numpy as np
import matplotlib.pyplot as mp
x = np.linspace(-np.pi, np.pi, 1000)
print(x.shape, x)
cos_y = np.cos(x) / 2
sin_y = np.sin(x)
mp.plot(x, cos_y) # 在内存中绘制
mp.plot(x, sin_y) # 在内存中绘制
mp.show() # 显示在屏幕上
线型 线宽 颜色
import matplotlib.pyplot as mp
"""设置线型 线宽 和 颜色参数
1. 线型: '-','--', 详情见下表
2. 线宽: 0 - 正无穷 (0代表看不见, 默认为2)
3. 颜色:
常见的英文单词 red blue green
常见的英文单词首字母 r b g
十六进制写法 # ffffff
rgb或rgba写法 (1, 1, 1) 或 (0.8, 0.6, 0.5)
4. 不透明度: alpha (0 - 1) 值越小越透明
"""
mp.plot(..., linestyle='线型', linewidth='线宽', color='颜色', alpha=0.5 ...)
# 参数简写
mp.plot(..., ls='线型', lw='线宽', c='颜色', alpha=0.5 ...)
线型符号
线型符号 | 描述 |
---|---|
- | 实线 |
-- | 虚线 |
: | 点线 |
-. | 点划线 |
o | 圆点 |
o- | 圆点及连线 |
案例:
# plt2.py
import numpy as np
import matplotlib.pyplot as mp
x = np.linspace(-np.pi, np.pi, 1000)
# print(x.shape, x)
cos_y = np.cos(x) / 2
sin_y = np.sin(x)
# print(cos_y, sin_y)
mp.plot(x, cos_y, linestyle='--', linewidth=1, color='violet')
mp.plot(x, sin_y, linestyle='-.', linewidth=3, color='lime')
mp.show()
中文字体
import matplotlib.pyplot as mp
# 导入字体管理器
import matplotlib.font_manager as mf
# 字体文件路径
font_file = '/System/Library/Fonts/PingFang.ttc'
# 设置字体
my_font =mf.FontProperties(fname=font_file)
# 设置中文刻度
mp.xticks(x_array, x_text_array, fontproperties=my_font)
坐标范围
用于控制图的大小和空白间距,坐标范围越大图形越小,反而反之
mp.xlim(x_min, x_max)
mp.ylim(y_min, y_max)
# plt3.py
import numpy as np
import matplotlib.pyplot as mp
x = np.linspace(-np.pi, np.pi, 1000)
# print(x.shape, x)
cos_y = np.cos(x) / 2
sin_y = np.sin(x)
# print(cos_y, sin_y)
mp.xlim(-5, 5) # 设置水平轴坐标范围
mp.ylim(-1.5, 1.5) # 设置垂直坐标范围
# 一般左右坐标范围间距为10%的空白
mp.xlim(x.min() * 1.1, x.max() * 1.1)
mp.ylim(sin_y.min() * 1.1, sin_y.max() * 1.1)
mp.plot(x, cos_y, linestyle='--', linewidth=1, color='violet')
mp.plot(x, sin_y, linestyle='-.', linewidth=3, color='lime')
mp.show()
坐标刻度
# x_val_list:为x轴刻度值列表, x_text_list: x轴值对应值的刻度文本列表
# 如果不写刻度文本,则按实际刻度数据显示, 如果书写则显示文本刻度
mp.xticks(x_val_list [, x_text_list])
# 设置y轴刻度显示数据
mp.yticks(y_val_list [, y_text_list])
# 隐藏x,y轴刻度
mp.xticks(())
mp.yticks(())
# plt4.py
mp.yticks([-1, -0.5, 0, 0.5, 1])
L = ['-π', '-π/2', '0', 'π/2', 'π']
L = [r'$-\pi$', r'$-\frac{\pi}{2}$', r'0', r'$\frac{\pi}{2}$', r'$\pi$']
# matplotlib支持的latex排版语法
# r规避python做字符串的转义, $..$表示做格式化转义, \frac{分子}{分母}
mp.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], L)
坐标轴
# 获取当前坐标轴, 不存在则创建 get current axis
ax = mp.gca()
# 关闭坐标轴显示,刻度和黑框都没有啦
mp.axis('off')
# 获取其中一个坐标轴对象, left,right,top,bottom分别为 左 右 上 下
ax_left = ax.spines['left']
# 设置坐标轴的位置
# type: 移动坐标轴的参照类型, 一般为'data',以数据坐标轴为参照
# val: 参照值,为0则将坐标轴移至轴刻度为0的位置
ax_left.set_postion((axis_type, val))
# 设置主坐标轴的位置: 左,右,上,下(left, right, top, bottom)
ax.xaxis.set_ticks_position('top') # 将x轴设置在顶部
ax.yaxis.set_ticks_position('left') # 将y轴设置在左侧
# 设置坐标数据的显示顺序
ax.invert_yaxis() # y轴反向(从上到下-从小到大显示数据)
# 设置坐标轴颜色
# color: 颜色值, 若为'none'则隐藏当前坐标轴
ax_left.set_color(color)
# plt5.py
import matplotlib.pyplot as mp
ax = mp.gca()
# 设置坐标系的位置
ax.spines['left'].set_position(('data', 0))
ax.spines['bottom'].set_position(('data', 0))
# 隐藏top, right坐标轴
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
图例
显示当前曲线的描述标签,需要执行mp.legend()才能显示
# 在plot绘制曲线时,给出label描述当前曲线的标签
mp.plot(…, label='图例标签', ...)
mp.legend(loc='best')
# loc可取值: upper left, upper right, lower left, lower right
# 分别对应为 左上 右上 左下 右下
# plt6.py
mp.plot(x, cos_y, linestyle='--', linewidth=1, color='violet', label=r'$y=\frac{1}{2}cos(x)$')
mp.plot(x, sin_y, linestyle='-.', linewidth=3, color='lime', label=r'$y=sin(x)$')
mp.legend(loc='upper left') # 左上
mp.show()
特殊点
# x_array, y_array 为散点坐标数组
mp.scatter(x_array, y_array,
marker='o', # 点形状:o为圆点, D为菱形...
s=60, # 点大小
edgecolor='', # 边缘色
facecolor='', # 填充色
zorder=3 # 图层编号, 值越大越显示在上面
)
备注
# x_array, y_array 为散点坐标数组
mp.annotate(
r'$...$', # 备注文本
xycoords='data', # 定位目标点使用的参照坐标系
xy=(1, 2), # 目标点的坐标
textcoords='offset points', # 定位文本位置使用的坐标系
xytext=(10, -30), # 备注文本的位置坐标
fontsize=14, # 字体大小
arrowprops=dict(
arrowstyle='->', # 箭头的样式
connectionstyle='angle3'# 箭头连接线的样式
)
)
特殊点和备注案例
import numpy as np
import matplotlib.pyplot as mp
# 生成点数据
xo = np.pi * 3 / 4
yo_cos = np.cos(xo) / 2
yo_sin = np.sin(xo)
# 绘制特殊点
mp.scatter([xo, xo], [yo_cos, yo_sin], s=60, facecolor='limegreen', edgecolor='red', zorder=3, marker='D')
# 绘制备注文本
for xy in [(xo, yo_cos), (xo, yo_sin)]:
mp.annotate(
r'$\frac{1}{2}cos(\frac{3\pi}{4})=-\frac{\sqrt{2}}{4}$',
xy=xy, xycoords='data',
xytext=(-90, -40), textcoords='offset points',
fontsize=14,
arrowprops=dict(arrowstyle='->',connectionstyle='arc3, rad=.2'))
mp.show()
图片示意图
图形窗口对象
mp.ffigure方法可以创建一个新的窗口,但是如果新窗口的title已经被创建过了,那么就把该title的旧窗口置为当前窗口,以后的绘图操作,都将针对当前窗口生效。
# title:窗口的标题
# figsize: 窗口的大小
# dpi:像素密度
# facecolor:图表的背景色
mp.figure('title', figsize=(4,3), dpi=120, facecolor='')
mp.show()
窗口参数
mp.title('title', fontsize=16) # 设置图表标题
mp.xlabel('x', fontsize=12) # x轴的描述文本
mp.ylabel('y', fontsize=12) # y轴的描述文本
mp.tick_params(labelsize=8) # 设置刻度标签字体大小
mp.grid(linestyle=':') # 绘制网格线
mp.tight_layout() # 紧凑布局
案例
# fig.py
import numpy as np
import matplotlib.pyplot as mp
x = np.linspace(-np.pi, np.pi, 1000)
cos_y = np.cos(x) / 2
cos_x = np.sin(x)
# figsize: 是在长,宽为xx英寸, dpi是指每英寸为多个像素点
mp.figure('Figure Object 1', figsize=(6, 5), dpi=120, facecolor='lightgray')
# 绘制图形标题
mp.title('Figure Object 1', fontsize=20)
# 绘制坐标轴标签
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
# 设置坐标轴刻度字体大小
mp.tick_params(labelsize=6)
# 绘制网格线
mp.grid(linestyle=':')
# show是阻塞函数,需要关闭图形,才能继续往下执行
# mp.show()
# 创建图像对象2
mp.figure('Figure Object 2', figsize=(6, 5), dpi=120, facecolor='lightgray')
mp.title('Figure Object 2', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=6)
mp.grid(linestyle=':')
# 将y=sin(x)绘制在图1
mp.figure('Figure Object 1')
mp.plot(x, cos_y, label=r'$y=\frac{1}{2}cos(x)$')
mp.legend(loc='upper left')
# 将y=sin(x)绘制在图2
mp.figure('Figure Object 2')
mp.plot(x, sin_y, label=r'$y=sin(x)$')
mp.legend(loc='upper left')
mp.show()
窗口子图
可以在一个图中对比和观察不同的图像,主要有三种布局方式: 矩阵式布局,栅格布局,自由布局
矩阵式布局
# 布局方式,1, 2, 3, 4分别为对应图号的排列
1 2
3 4
# rows: 行数, columns: 列数, num: 子图编号
mp.subplot(rows, columns, num)
mp.subplot(3, 3, 5) # 把3行3列的5号图设为当前绘图区域
mp.subplot(331) # 把3行3列的1号图设为当前绘图区域
# 绘图区域中添加文本, num为子图编号,0.5,0.5为文本相对位置坐标
mp.text(0.5, 0.5, num, ha='center', va='center', size=36, alpha=0.5)
案例: 绘制九宫格
# subplot.py
import matplotlib.pyplot as mp
mp.figure('Subplot', facecolor='lightgray')
for i in range(1, 10):
mp.subplot(3, 3, i)
# 在窗前绘图区域写文字
mp.text(0.5, 0.5, i, size=36, alpha=0.8, ha='center', va='center')
mp.xticks([])
mp.yticks([])
mp.tight_layout()
mp.show()
栅格式布局
栅格式(网格式)布局支持单元格的合并,使用时需要借助于栅格定位器
import matplotlib.gridspec as mg
mp.figure(..)
# 创建GridSpec对象,(3行3列) --> 返回数组对象
gs = mg.GridSpec(3, 3)
# 把GridSpec中第一行的前两列合并为一个子图
# subplot(栅格定位器[行, 列])
mp.subplot(gs[0, :2])
mp.show()
案例
# 栅格定位器
import numpy as np
import matplotlib.pyplot as mp
import matplotlib.gridspec as mg
mp.figure('Grid Layout', facecolor='lightgray')
# 创建栅格定位器 --> 数组
gs = mg.GridSpec(3, 3)
# 创建子图
mp.subplot(gs[0, :2])
mp.xticks(())
mp.yticks(())
mp.text(0.5, 0.5, '1', ha='center', va='center', alpha=.5, fontsize=36)
mp.subplot(gs[1:, 0])
mp.xticks(())
mp.yticks(())
mp.text(0.5, 0.5, '2', ha='center', va='center', alpha=.5, fontsize=36)
mp.subplot(gs[:2, 2])
mp.xticks(())
mp.yticks(())
mp.text(0.5, 0.5, '3', ha='center', va='center', alpha=.5, fontsize=36)
mp.subplot(gs[2, 1:])
mp.xticks(())
mp.yticks(())
mp.text(0.5, 0.5, '4', ha='center', va='center', alpha=.5, fontsize=36)
mp.subplot(gs[1, 1])
mp.xticks(())
mp.yticks(())
mp.text(0.5, 0.5, '5', ha='center', va='center', alpha=.5, fontsize=36)
# 紧凑布局
mp.tight_layout()
mp.show()
自由布局
通过自由布局,可以呈现图中图的效果
mp.figure()
# 设置图表的位置,需要给出左下角点坐标与宽、高即可 (相对左边)
# 0.03: 左下角点的横坐标
# 0.04: 左下角点的纵坐标
# 0.94: 图表的宽度
# 0.92: 图表的高度
mp.axes([0.03, 0.04, 0.94, 0.92])
mp.text(....)
mp.show()
案例
# sub3.py
import numpy as np
import matplotlib.pyplot as mp
import matplotlib.gridspec as mg
mp.figure('Free Layout', facecolor='lightgray')
# 浅灰色区域为1
mp.axes([0.03, 0.038, 0.94, 0.929])
mp.xticks(())
mp.yticks(())
mp.text(0.5, 0.5, '1', ha='center', va='center', alpha=.5, fontsize=36)
# 浅灰色区域为1
mp.axes([0.63, 0.078, 0.31, 0.308])
mp.xticks(())
mp.yticks(())
mp.text(0.5, 0.5, '2', ha='center', va='center', alpha=.5, fontsize=36)
mp.show()
刻度定位器
# 格式: 刻度定位器 = xxxLocator(定位规则)
# ax.xaxis, ax.yaxis 分别为水平坐标轴和垂直坐标轴
# 获取当前坐标轴
ax = mp.gca()
# 设置横轴的主刻度定位器为多点定位器,主刻度间隔为1
ax.xaxis.set_major_locator(mp.MultipleLocator(1))
# 设置横轴的次刻度定位器为NullLocator()(将不会显示次刻度)
ax.xaxis.set_minor_locator( mp.NullLocator() )
案例:
# tick.py
import numpy as np
import matplotlib.pyplot as mp
import matplotlib.gridspec as mg
mp.figure()
locators = [
'mp.NullLocator()',
# nbins最多绘制几个, 间距从steps中取一个
'mp.MaxNLocator(nbins=3, steps=[1, 3, 5, 7, 9])',
# 固定点的刻度定位
'mp.FixedLocator(locs=[0, 2.5, 5, 7.5, 10])',
# 自动定位,自动选择步长
'mp.AutoLocator()',
# offset为起始偏移,base为基础步长
'mp.IndexLocator(offset=0.5, base=1.5)',
# 默认步长为1
'mp.MultipleLocator(1)',
# numticks为刻度数量
'mp.LinearLocator(numticks=21)',
# subs为指数公差, 刻度上的数的都为 2 ^ x , 0.5 = 2 ^ -1, 1 = 2 ^ 0, 其中subs为的公差 刻度 = (2 ^ x) * subs
'mp.LogLocator(base=2, subs=[2.0])',
'mp.LogLocator(base=3, subs=[1.0])'
]
n_locators = len(locators)
for i, locator in enumerate(locators):
# 绘制子图
mp.subplot(n_locators, 1, i + 1)
mp.xlim(0, 10)
mp.ylim(-1, 1)
mp.yticks(())
ax = mp.gca()
ax.spines['left'].set_color('none')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data', 0))
# 设置主刻度, eval()解释字符串
ax.xaxis.set_major_locator(eval(locator))
# 设置次刻度的间距为0.1
ax.xaxis.set_minor_locator(mp.MultipleLocator(0.1))
# 绘制一个透明线,不然IndexLocator会出错
mp.plot(np.arange(11), np.zeros(11), c='none')
# 添加文字
mp.text(5, 0.3, locator[3:], ha='center', va='center')
mp.tight_layout()
mp.show()
刻度网格线
ax = mp.gca()
# 绘制刻度网格线
ax.grid(
which='', # 'major''minor' 绘制主刻度/次刻度网格线
axis='', # 'x'/'y'/'both' 绘制x轴/y轴的刻度网格线 linewidth=1,
linestyle='',
color='',
alpha=0.5
)
案例:减幅正弦波
import numpy as np
import matplotlib.pyplot as mp
x = np.linspace(-10, 10, 1000)
# sinc(x)减幅正弦
y = 8 * np.sinc(x)
mp.figure('Grid', facecolor='lightgray')
mp.title('Grid', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
ax = mp.gca()
# 设置刻度定位器
ax.xaxis.set_minor_locator(mp.MultipleLocator(0.5))
ax.yaxis.set_minor_locator(mp.MultipleLocator(0.4))
# 设置网格线
ax.grid(which='major', axis='both', linewidth=0.75, linestyle='-', color='orange')
ax.grid(which='minor', axis='both', linewidth=0.25, linestyle='-', color='orange')
mp.plot(x, y, c='dodgerblue', label=r'$y=8sinc(x)$')
mp.legend()
mp.show()
半对数坐标轴
y轴将会以指数方式递增,放大局部的变化趋势
mp.figure()
# mp.plot()改为mp.semilogy()方法绘制曲线即可
mp.semilogy(x, y, ...)
mp.show()
极坐标系
某些情况下极坐标系适合显示与角度有关的图像,例如雷达。它可以处理极径ρ(rho)与极角θ(theta)之间的线性关系。笛卡尔坐标系难以用方程描述(x-y),而是用极坐标系将大大简化公式,便于分析图像特性,如阿基米德线
mp.figure(...)
# 创建极坐标轴,显示title之后就显示坐标系了,所以需在他之前创建坐标系
ax = gca(projection='Polar')
# theta: 极角, rho: 极径
mp.plot(theta, rho)
mp.title(...)
案例: 阿基米德线
# polar.py
import numpy as np
import matplotlib.pyplot as mp
t = np.linspace(0, 2 * np.pi, 1000)
r_spiral = 0.8 * t
r_rose = 5 * np.sin(6 * t)
mp.figure('Polar', facecolor='lightgray')
# 创建坐标系, 笛卡尔坐标系是x,y坐标系
mp.gca(projection='polar')
# 显示title之后就显示坐标系了,所以需在他之前创建坐标系
mp.title('Polar', fontsize=20)
mp.xlabel(r'$\theta$', fontsize=14)
mp.ylabel(r'$\rho$', fontsize=14)
mp.grid(linestyle=':')
mp.plot(t, r_spiral, c='dodgerblue', label=r'$\rho=0.8\theta$')
mp.plot(t, r_rose, c='orangered', label=r'$\rho=5sin(6\theta)$')
mp.legend()
mp.show()
绘图类型
折线图
显示数据的变化趋势,反映事物的变化情况(变化)
import matplotlib.pyplot as mp
# 绘制曲线图 x_array为水平坐标系数组, y_array为垂直坐标系数组
mp.plot(x_array, y_array)
# 绘制垂直线, 给出x坐标, y的最小值和最大值
mp.vlines(x_val, ymin, ymax)
# 绘制水平线, 给出y坐标, x的最小值和最大值
mp.vlines(y_val, xmin, xmax)
综合案例
import random
from matplotlib.pyplot as mp
from matplotlib.font_manager as mf
# 设置中文字体
font_file = '/System/Library/Fonts/PingFang.ttc'
my_font = mf.FontProperties(fname=font_file)
# 添加数据
x = range(0, 120)
y = [random.randint(20, 35) for i in range(120)]
# 创建图像窗口,窗口标题,轴标签,刻度参数,网格线型
mp.figure('TempOfTime', facecolor='lightgray')
mp.title('温度时间变化曲线', fontsize=20, fontproperties=my_font)
mp.xlabel('时间', fontsize=14, fontproperties=my_font)
mp.ylabel('温度', fontsize=14, fontproperties=my_font)
# 设置x轴,y轴标签中文描述
x_labels = ['10点{}分'.format(i) for i in range(60)]
x_labels += ['11点{}分'.format(i) for i in range(60)]
mp.xticks(list(x)[::10], x_labels[::10], rotation=45, fontproperties=my_font)
mp.yticks(y[::1], rotation=45, fontproperties=my_font)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 绘制图形
mp.plot(x, y, c='dodgerblue', lw=3, ls='-', label='TempOfTime')
mp.legend('upper right')
mp.tight_layout()
mp.show()
填充图
以某种颜色自动填充两条曲线的闭合区域
mp.fill_between(
x, # 水平坐标
sin_x, # 起点垂直坐标
cos_x, # 终止垂直坐标
sin_x < cos_x, # 填充条件,若为True时填充
color='', # 颜色
alpha=0.5 # 透明度
)
在定义域[0, 8π]内绘制两条曲线: y = sin(x) , y = cos(x/2)/2
# fill.py
import numpy as np
import matplotlib.pyplot as mp
# 生成视图数据
n = 1000
x = np.linspace(0, 8 * np.pi, n)
sin_y = np.sin(x)
cos_y = np.cos(x / 2) / 2
# 创建图像窗口,窗口标题,轴标签,刻度参数,网格线型
mp.figure('Fill', facecolor='lightgray')
mp.title('Fill', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 绘制两条曲线
mp.plot(x, sin_y, c='dodgerblue', label=r'$y=sin(x)$')
mp.plot(x, cos_y, c='orangered', label=r'$y=\frac{1}{2}cos(\frac{x}{2})$')
# 绘制填充区域
mp.fill_between(x, cos_y, sin_y, cos_y < sin_y, color='dodgerblue', alpha=0.5)
mp.fill_between(x, cos_y, sin_y, cos_y > sin_y, color='orangered', alpha=0.5)
# 绘制图例
mp.legend()
# 显示图形
mp.show()
散点图
用于判断变量是否存在数量关联趋势,展示离群点(关系)
# numpy.random模块提供了normal函数用于产生符合正态分布的随机数
n = 100
# 产生n个符合正态分布规律的随机数
# 172:期望
# 20:标准差(标准差越小,越集中;标准差越大,越分散)
x = np.random.normal(172, 20, n)
y = np.random.normal(65, 10, n)
绘制散点图的相关API:
mp.scatter(
x, y,
marker='',
s=60,
edgecolor='',
facecolor='',
zorder=3
)
案例
# scatter.py
import numpy as np
import matplotlib.pyplot as mp
n = 500
x = np.random.normal(172, 20, n)
y = np.random.normal(65, 10, n)
mp.figure('Students', facecolor='lightgray')
mp.title('Students List', fontsize=16)
mp.xlabel('Height', fontsize=14)
mp.ylabel('Weight', fontsize=14)
mp.tick_params(labelsize=12)
mp.grid(linestyle=':')
mp.scatter(x, y, marker='o', s=50,
color='dodgerblue', alpha=0.5,
zorder=3, label='Stduent')
mp.legend()
mp.show()
直方图
绘制连续数据,显示一组或多组数据的分布情况(统计)
mp.hist(
samples, # 样本数据
100, # 分组数量
normed=True, # 是否符合正态分布
edgecolor='steelblue',
facecolor='deepskyblue',
label='Normal'
)
案例
# norm.py
import numpy as np
import matplotlib.pyplot as mp
samples = np.random.normal(size=10000)
print(samples.mean(), samples.std())
x = np.linspace(samples.min(), samples.max(), 1000)
y = np.exp(-x ** 2 / 2) / np.sqrt(2 * np.pi)
mp.figure('Normal Distribution', facecolor='lightgray')
mp.title('Normal Distribution', fontsize=20)
mp.xlabel('Sample', fontsize=14)
mp.ylabel('Occurrence', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')
# 绘制直方图
mp.hist(samples, 100, normed=True, edgecolor='steelblue', facecolor='deepskyblue', label='Normal')
mp.plot(x, y, c='orangered', label='Probability')
mp.legend()
mp.show()
条形图 (柱状图)
绘制离散数据,显示各组数据大小的区别
mp.figure()
mp.bar(
x, # 水平坐标数组
y, # 每个柱子绘制的高度
width, # 每个柱子的宽度 color='', # 颜色
label='', # 标签名(供legend使用)
alpha=0.5
)
案例
import numpy as np
import matplotlib.pyplot as mp
# 生成视图数据
apples = [9, 1, 23, 64, 89, 12, 36, 48, 93, 24, 85, 86]
oranges = [19, 23, 64, 92, 37, 46, 28, 54, 28, 46, 93, 43]
# 设置图形窗口对象
mp.figure('Bar', facecolor='lightgray')
mp.title('Bar', fontsize=18)
mp.xlabel('Date', fontsize=14)
mp.ylabel('Price', fontsize=14)
mp.ylim(-40, 40)
mp.tick_params(labelsize=12)
mp.grid(linestyle=':')
x = np.arange(len(apples))
# 绘制条形图
mp.bar(x, apples, 0.4, color='dodgerblue', label='Apple')
# 0.4为条形图宽度, x + 0.4代表条形图进行一定的偏移, 如果取的数据为-,则绘制在坐标轴下方
mp.bar(x + 0.4, -oranges, 0.4, color='orangered', label='Oranges')
mp.xticks(x, [
'Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
'Nov', 'Dec'])
mp.legend()
mp.show()
饼状图
用于查看数据所占整体的比例情况,统计比重
mp.pie(
values, # 值列表 (列表对象)
spaces, # 扇形之间的间距列表
labels, # 标签列表
colors, # 颜色列表
'%d%%', # 标签所占比例的格式化字符串
shadow=True, # 是否添加阴影
startangle=90, # 起始角度, 默认为0
radius=1 # 大饼半径
)
案例
# pie.py
import numpy as np
import matplotlib.pyplot as mp
# 生成视图数据
values = [26, 17, 21, 29, 11]
spaces = [0.1, 0.01, 0.01, 0.01, 0.01]
labels = ['Python', 'Javascript', 'C++', 'Java', 'PHP']
colors = ['dodgerblue', 'orangered', 'limegreen', 'gold', 'red']
# 创建图像窗口
mp.figure('Pie', facecolor='lightgray')
mp.title('Pie', fontsize=20)
# 绘制饼图, 逆时针绘制, 可以指定起始角度
mp.pie(values, spaces, labels, colors, '%d%%', shadow=True, startangle=90, radius=1.2)
mp.show()
等高线图
整理等高线数据需要网格点坐标矩阵,也需要每个点的高度,先有曲面才有等高线,所以等高线属于3D数学模型的范畴。
cntr = mp.contour(
x, # 网格x点阵坐标
y, # 网格y点阵坐标
z, # 点阵z坐标,即每个坐标点的高度
8, # 梯度数,把整体的高度分成8份
colors='', # 每条等高线的颜色
linewidths=0.5 # 每条等高线的宽度
)
# 为等高线添加标签
mp.clabel(cntr, inline_spacing=1, fmt='%.1f', fontsize=10) # 为等高线每一部分设置颜色
# 采用颜色映射的等高线, cmap为映射映射带,按照高度的变化映射不同的颜色
mp.contourf(x, y, z, 8, cmap='jet')
案例
# contour.py
import numpy as np
import matplotlib.pyplot as mp
# 生成视图数据
n = 1000
# 让x,y与曲面相交 - 网格化
x, y = np.meshgrid(
np.linspace(-3, 3, 1000),
np.linspace(-3, 3, 1000)
)
z = (1 - x/2 + x**5 + y**3)*np.exp(-x**2 -y**2)
# 创建图像窗口
mp.figure('Contour', facecolor='lightgray')
mp.title('Contour', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 将不同等高线用颜色填充,海拔越高越红,越低越蓝
mp.contourf(x, y, z, 8, cmap='jet')
# 绘制等高线图,8为梯度,梯度越多,线越多
cntr = mp.contour(x, y, z, 10, colors=['black', 'green'], linewidths=[0.5, 1])
# 在等高线对象上标注高度
mp.clabel(cntr, inline_spacing=1, fmt='%.1f', fontsize=10)
mp.show()
热力图 (热成像图)
# 把矩阵matrix_z图形化,使用cmap的颜色表示矩阵中每个元素的热度值
# origin: y轴方向
# 'lower': y轴的0在下方
# 'upper': y轴的0在上方
mp.imshow(matrix_z, cmap='jet', origin='lower')
案例
# hot.py
import numpy as np
import matplotlib.pyplot as mp
# 生成视图数据
n = 1000
# 让x,y与曲面相交 - 网格化
x, y = np.meshgrid(
np.linspace(-3, 3, 1000),
np.linspace(-3, 3, 1000)
)
z = (1 - x/2 + x**5 + y**3)*np.exp(-x**2 -y**2)
# 创建图像窗口
mp.figure('Contour', facecolor='lightgray')
mp.title('Contour', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 绘制热力图
mp.imshow(z, cmap='jet', origin='low')
mp.show()
3D图像绘制
使用matplotlib绘制3D图像,需要先获取3D坐标轴,调用ax3d对象的方法绘制3D图形。
from mpl_toolkits.mplot3d import axes3d
ax3d = mp.gca(projection='3d')
# 绘制3d线宽图
ax3d.plot_wireframe()
# 绘制3d曲面图
ax3d.plot_surface()
# 绘制散点散点图
ax3d.scatter()
3D散点图
ax = mp.gca(projection='3d')
ax.scatter(
x_array, # x坐标
y_array, # y坐标
z_array, # z坐标
s=60, # 点大小
marker='o', # 形状
edgecolor='',
facecolor='',
c=d, # 颜色映射参考的数组
cmap='' # 所使用的颜色映射
)
案例
# s3.py
import numpy as np
import matplotlib.pyplot as mp
from mpl_toolkits.mplot3d import axes3d
# 生成数据
n = 1000
x = np.random.normal(0, 1, n)
y = np.random.normal(0, 1, n)
z = np.random.normal(0, 1, n)
# 利用距离来表示颜色
d = np.sqrt(x ** 2 + y ** 2 + z ** 2)
# 绘制图像
mp.figure('3D Scatter', facecolor='lightgray')
ax = mp.gca(projection='3d')
mp.title('3D Scatter')
ax.set_xlabel('x', fontsize=14)
ax.set_ylabel('y', fontsize=14)
ax.set_zlabel('z', fontsize=14)
mp.tick_params(labelsize=10)
# c为颜色矩阵, 颜色,大小,形状也可以表示特征值。。
ax.scatter(x, y, z, s=60, c=d, cmap='jet_r', alpha=0.5)
mp.show()
3D线宽图
ax3d.plot_wireframe(
x, y, z, # 网格点坐标矩阵,和每个点的z轴值
rstride=30, # 行跨距
cstride=30, # 列跨距
linewidth=1, # 线宽
color='' # 颜色
)
3D曲面图
ax3d.plot_surface(
x, y, z,
rstride=30, cstride=30, cmap='jet'
)
3D曲面和线宽图案例
# p3.py
import numpy as np
import matplotlib.pyplot as mp
from mpl_toolkits.mplot3d import axes3d
# 生成视图数据
n = 1000
# 让x,y与曲面相交 - 网格化
x, y = np.meshgrid(
np.linspace(-3, 3, 1000),
np.linspace(-3, 3, 1000)
)
z = (1 - x/2 + x**5 + y**3)*np.exp(-x**2 -y**2)
mp.figure('3D WireFrame1', facecolor='lightgray')
ax = mp.gca(projection='3d')
mp.title('3D WireFrame1', fontsize=20)
ax.set_xlabel('x', fontsize=14)
ax.set_ylabel('y', fontsize=14)
ax.set_zlabel('z', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 绘制三维线宽图
ax.plot_wireframe(x, y, z, rstride=30, cstride=30, linewidth=0.5, color='dodgerblue')
mp.figure('3D SurFace', facecolor='lightgray')
ax = mp.gca(projection='3d')
mp.title('3D SurFace', fontsize=20)
ax.set_xlabel('x', fontsize=14)
ax.set_ylabel('y', fontsize=14)
ax.set_zlabel('z', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 绘制三维线宽图
ax.plot_surface(x, y, z, rstride=30, cstride=30, cmap='jet')
mp.show()
简单动画
动画即是在一段时间内快速连续重新绘制图像的过程。连续显示的静态画面生成动画效果(30祯/s 看不出静态 ,电影50祯/s), matplotlib提供了方法可以实现简单动画,定义一个update函数用于即时更新图像。
import matplotlib.animation as ma
# update中编写更新图像的代码,每隔一段时间将会自动调用
def update(number):
pass
# 每隔30毫秒,执行一次update函数,针对当前窗体绘制图像
anim = ma.FuncAnimation(mp.gcf(), update, interval=30)
mp.show()
案例: 气泡的增长和破裂
# bub.py
import numpy as np
import matplotlib.pyplot as mp
import matplotlib.animation as ma
n_bubbles = 100
# 复合数据类型
bubbles = np.zeros(n_bubbles, dtype=[
('position', float, 2),
('size', float, 1),
('growth', float, 1),
('color', float, 4)
])
# 100行2列,均匀分布,正态分布
bubbles['position'] = np.random.uniform(0, 1, (n_bubbles, 2))
bubbles['size'] = np.random.uniform(50, 750, n_bubbles)
bubbles['growth'] = np.random.uniform(30, 150, n_bubbles)
bubbles['color'] = np.random.uniform(0, 1, (n_bubbles, 4))
mp.figure('Bubbles', facecolor='lightgray')
mp.title('Bubbles')
mp.xticks(())
mp.yticks(())
# 散点图有返回对象
sc = mp.scatter(bubbles['position'][:, 0], bubbles['position'][:, 1], s=bubbles['size'], c=bubbles['color'])
# 更新函数
def update(number):
# number代表当前绘制的帧号
# print('update:', number)
bubbles['size'] += bubbles['growth']
# 随机选择一个泡泡破裂
burst = number % n_bubbles
# bubbles['position'][burst] 每一行就是 x, y坐标
bubbles['position'][burst] = np.random.uniform(0, 1, 2)
bubbles['size'][burst] = 0
bubbles['growth'][burst] = np.random.uniform(30, 150)
bubbles['color'][burst] = np.random.uniform(0, 1, 4)
# 更换位置属性
sc.set_offsets(bubbles['position'])
# 更新散点图的size
sc.set_sizes(bubbles['size'])
# 更新颜色
sc.set_facecolor(bubbles['color'])
# mp.gcf()为当前窗口
anim = ma.FuncAnimation(mp.gcf(), update, interval=10)
mp.show()
使用生成器函数提供数据,实现动画绘制
很多情况下,绘制动画的参数是动态获取的,matplotlib支持定义生成生成器函数,用于生成数据,然后自动把数据交给update函数更新图像
def update(data):
pass·
def generator():
yield data
# 每10毫秒,调用生成器,把生成器yield出的数据交给update函数执行
anim = ma.FuncAnimation(mp.gcf(), update, generator,
interval=10)
# sig.py
import numpy as np
import matplotlib.pyplot as mp
import matplotlib.animation as ma
mp.figure('Signal', facecolor='lightgray')
mp.title('Signal')
mp.xlabel('Time', fontsize=14)
mp.ylabel('Signal', fontsize=14)
ax = mp.gca()
ax.set_ylim(-3, 3)
ax.set_xlim(0, 10)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 曲线对象
pl = mp.plot([], [], c='orangered')[0]
# 设置曲线数据缓存区(空)
pl.set_data([], [])
def update(data):
t, v = data
# 获取曲线数据缓冲区原有数据x, y点阵
x, y = pl.get_data()
x.append(t)
y.append(v)
# 当前曲线画到边界时,坐标系不断移动
x_min, x_max = ax.get_xlim()
if t >= x_max:
ax.set_xlim(t - (x_max - x_min), t)
# 更新坐标系的绘制
ax.figure.canvas.draw()
# 设置曲线数据缓冲区
pl.set_data(x, y)
def generator():
t = 0
while True:
v = np.sin(2 * np.pi * t) * np.exp(np.sin(0.3 * np.pi * t))
yield t, v
t += 0.05
anim = ma.FuncAnimation(mp.gcf(), update, generator, interval=0.05)
# 更新函数
mp.show()
图片显示
图片本质上是一系列行列组成的像素点,像素就是显示器的发光点(红,绿,蓝--调整强度呈现出不同的颜色),其中将(129, 200, 300) —(R, G, B)红绿蓝像素点灰度化 (0-255) —>其实就是颜色的 gray映射 —> 灰度图像
# gray.py
import scipy.misc as sm
import matplotlib.pyplot as mp
# 利用scipy多媒体库读出图片矩阵, True代表映射成灰度,转为成np中uint8类型
image = sm.imread('lily.jpg', True).astype(np.uint8)
# 彩色:(512, 512, 3) uint8 , 灰度:(512, 512) uint8
print(image.shape, image.dtype)
print(image)
mp.figure('Image', facecolor='lightgray')
mp.title('Image')
# 关闭坐标轴显示,刻度和黑框都没有啦
mp.axis('off')
mp.imshow(image, cmap='gray')
mp.show()