Matplotlib - Python绘图库

Matplotlib

matplotlib是python的一个数学绘图库,可以很方便的绘制出出版质量级别的图形

功能概述

  1. 基本绘图
    1. 绘制曲线
    2. 设置线型、线宽、颜色
    3. 设置坐标轴范围及刻度
    4. 设置坐标轴属性
    5. 显示图例
    6. 绘制特殊点
    7. 添加备注
  2. 高级图形绘制
    1. 绘制子图
    2. 刻度定位器、刻度网格线
    3. 半对数坐标
    4. 散点图
    5. 填充图
    6. 条形图、饼状图
    7. 等高线图
    8. 热成像图
    9. 极坐标系
    10. 三俄日曲面
    11. 简单动画

基本绘图

绘图核心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()

图片示意图

annotate

图形窗口对象

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()
grid
自由布局

通过自由布局,可以呈现图中图的效果

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()
free
刻度定位器
# 格式: 刻度定位器 = 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()
polar

绘图类型

折线图

显示数据的变化趋势,反映事物的变化情况(变化)

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()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容