Skip to content

Matplotlib

Starslayerx edited this page Apr 4, 2022 · 19 revisions

本文档介绍Python中数据可视化,不仅仅包含Matplotlib这个库 Matplotlib

import matplotlib.pyplot as plt
%matplotlib inline    # %matplotlib widget 交互式

# 修正字体
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签(若系统没有该字体要下载安装)
plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号

简单介绍

Matplotlib有四类基础类型的对象容器:Figure、Axes、Axis、Tick。figure即图片本身,负责图形大小、位置;Axes负责坐标轴位置、绘图;Axis负责坐标轴的设�置等;Tick负责格式化样式等。下面是Matplotlib figure的组成 matplotlib_figure

子图操作

matplotlib绘制的图都位于figure对象中,可以使用figure方法生成一个新的图片

fig = plt.figure()

此时的图为一个空白图,可以在该图上添加一个或多个子图

  • 使用add_subplot添加子图
# 创建2*2个子图的1~3图
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)

agg_subplot返回Axes Subplot对象,使用这些对象可以直接在子图上调用对象的方法进行绘图,若此时直接使用plt.plot进行绘图,则会在最后创建的子图上进行绘图。

ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.4)
ax2.scatter(np.arange(30), np.arange(30) + 3*np.random.randn(30))
plt.plot(np.random.randn(50).cumsum(), 'k--')    # 直接绘制在最后一个子图上

subfigures

  • subplots函数
    subplots函数可以绘制x*y个子图,返回一个figure对象和一个Axes对象:

    fig, axes = subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,subplot_kw=None, 
    gridspec_kw=None, **fig_kw)
    • fig为figure对象,可以用来保存图片使用`fig.savefig('name')
    • axes可以通过二维数组的方法来访问子图,例如axes[0,1]这样
    • nrows and ncols:行和列的个数。
    • sharex and sharey: 是否共享x y 轴。
    • subplot_kw: 传入add_subplot的关键字参数字典,用于生成子图。
    • **fig_kw:生成图片时使用的figure参数,如 figsize、facecolor等。
  • 调整子图间距

    subplots_adjust(left=None, bootm=None, right=None, top=None, wspace=None, hspce=None)
    • left: 子图左边缘的位置
    • right: 子图右边缘的位置
    • bottom: 子图底部边缘的位置
    • top: 子图顶端边缘的位置
    • wspace: 子图只之间的宽度
    • hspace: 每行子图之间padding的高度

    子图之间若出现遮挡,也可以使用tight_layout方法自动调整,也支持使用参数自行调整

    plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)

合并子图

x = np.linspace(0, 2 * np.pi, 200)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.sin(x*x)
y4 = x*np.sin(x)

ax1 = plt.subplot(2, 3, 1)
ax1.plot(x, y1, 'r', label = '$sin(x)$')
plt.legend(loc = 1) # 调整图例位置,1代表右上角

ax2 = plt.subplot(2, 3, 2)
ax2.plot(x, y2, 'b--', label = '$cos(x)$')
plt.legend()

ax3 = plt.subplot(2, 3, (3, 6)) # 3,6窗口合并
ax3.plot(x, y3, 'k--', label = '$sin(x^2)$')
plt.legend()

ax4 = plt.subplot(2, 3, (4, 5)) # 4,5窗口合并
ax4.plot(x, y4, 'k--', label = '$xsin(x)$')
plt.legend()

plt.show()

combine

颜色、标记和线类型

下面是plot函数的详细介绍

plot(x, y, linestyle, linewidth, color, marker, markersize, markeredgecolor, markerfacecolor, markeredgewidth, label, alpha)

其中x为x轴数值,y为y轴数值,此外也可以传入多个x1, y1, x2, y2同时绘制多个图,下面为其他参数解释:

  • linestyle: 折线类型,实线、虚线和点画线等
  • linewidth: 折线宽度
  • marker: 为折线图添加点,并设置形状
  • markersize: 点的大小
  • markeredgecolor: 点的边框颜色
  • markerfacecolor: 点的填充颜色
  • markeredgewidth: 点的边框宽度
  • label: 折线图标签(用于标签)
  • alpha: 折线图透明度

还有绘制其他形状图形的常用函数

函数 说明
pie 绘制饼状图
bar 绘制柱状图
hist 绘制二维直方图
scatter 绘制散点图

下面是调整绘图样式的详细参数选项

符号参数 可选类型 说明
color 线条颜色 b 蓝色
c 青色
g 绿色
k 黑色
m 洋红色
r 红色
w 白色
y 黄色
linestyle 线条样式 - 实线
-- 虚线
-. 点画线
: 点线
marker 数据点形状 .
o 圆圈
* 星形
x 十字
s 正方形
p 五角星
d 钻石
h 六角形
+ 加号
| 竖线
^ < > 各种三角形
1234 Tropod向上下左右各个方向

特殊属性 drawstyle='steps-post'绘制梯形图形

刻度、标签和图例

  • 设置标题、轴标签、刻度和刻度标签
    设置标题使用set_title方法

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.set_title('My first matplotlib plot')

    使用xlim函数不加参数返回当前x轴范围,加上参数后可以设置x轴范围

    plt.xlim([0,10]) # 设置x轴范围从0到10

    使用set_xticksset_xticklabels分别设置x轴刻度和标签(指出要显示的刻度,并在下面写个标签,可以为数据也可以为字符串)

    对于y轴同理,将x换成y即可

    还可以使用set方法批量设置绘图属性

    props = {
        'title': 'My first matplotlib plot',
        'xlabel': 'Stages'
    }
    ax.set(**props)
  • 添加图例

    plt.plot(np.random.randn(1000).cumsum(), 'k', label = 'one')
    plt.legend(loc='best')

    legend函数显示标签,与之前绘图添加的label对应,参数loc可以使用'best'会自动将图例放在合适的地方。

  • 添加图像
    添加图像需要生成patch(补丁)对象,并使用ax.add_patch(shp)将其加入子图中

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

rect = plt.Rectangle((0.2, 0.75), 0.4, 0.25, color='k', alpha=0.3)
circ = plt.Circle((0.7, 0.2), 0.15, color='b', alpha=0.3)
pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]], color='g', alpha=0.5)

ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)

figure

轴域

轴域axes和subplot比较像,都是figure上的图,好比画板和画纸的关系

  • 获取当前axes对象
    plt.gca()

    gca就是 get current axes

注解

  • 注解
    使用text方法在图中位置添加注释

    plt.text(x, y, 'string', family='font', fontsize=n)
    • x y: 分别为注释的位置
    • 'string': 注释内容
    • family: 注释字体
    • fontsize: 字体大小
      使用arrow函数可以添加箭头,和注释搭配起来很好用
    matplotlib.pyplot.arrow(x, y, dx, dy, hold=None, **kwargs)

    参数

    • x, y: 箭头起点做I报
    • dx, dy: 箭头在xy轴上的长度
    • width: 箭头宽度,默认0.001
    • length_includes_head: 头是否包含在长度之中,默认False
    • head_width: 箭"头"的宽度,默认 3*width
    • head_length: 箭"头"的长度,默认 1.5*head_width
    • shape: [‘full’, ‘left’, ‘right’],箭头形状,默认‘full’
  • 添加带箭头的注解
    该函数官网详解

    Axes.annotate(s, xy, *args, **kwargs)
    • s:注释文本的内容
    • xy:被注释的坐标点,二维元组形如(x,y)
    • xytext:注释文本的坐标点,也是二维元组,默认与xy相同
    • textcoords: 注释文本的坐标系属性,默认与xycoords属性值相同,也可设为不同的值。除了允许输入xycoords的属性值,还允许输入以下两种:
      属性值 含义
      'offset points' 相对于被注释点xy的偏移量(单位是点)
      'offset pixels' 相对于被注释点xy的偏移量(单位是像素)
    • xycoords:被注释点的坐标系属性,允许输入的值如下
      属性值 含义
      'figure points' 以绘图区左下角为参考,单位是点数
      'figure pixels' 以绘图区左下角为参考,单位是像素数
      'figure fraction' 以绘图区左下角为参考,单位是百分比
      'axes points' 以子绘图区左下角为参考,单位是点数
      'axes pixels' 以子绘图区左下角为参考,单位是像素数
      'axes fraction' 以子绘图区左下角为参考,单位是百分比
      'data' 以被注释的坐标点xy为参考
      'polar' 不使用本地数据坐标系,使用极坐标系
    • arrowprops:箭头的样式,dict(字典)型数据,如果该属性非空,则会在注释文本和被注释点之间画一个箭头。如果不设置'arrowstyle' 关键字,则允许包含以下关键字
      关键字 说明
      width 箭头的宽度(单位是点)
      headwidth 箭头头部的宽度(点)
      headlength 箭头头部的长度(点)
      shrink 箭头两端收缩的百分比(占总长)
      * matplotlib.patches.FancyArrowPatch中的关键字

该函数可以用来给Networkx绘制有重复边的图

pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos)
ax = plt.gca()
for e in G.edges:
    ax.annotate("",
                xy=pos[e[0]], xycoords='data',    # e[0]为边起点
                xytext=pos[e[1]], textcoords='data', # e[1]为边终点
                arrowprops=dict(arrowstyle="->", color="0.5",
                                shrinkA=5, shrinkB=5,
                                patchA=None, patchB=None,
                                connectionstyle="arc3,rad=rrr".replace('rrr',str(0.3*e[2])), ),
                )
plt.axis('off')
plt.show()

绘图风格

plt.style.use('seaborn-whitegrid')

更多风格可参考:Style sheets reference

饼状图

data = [0.4,0.3,0.1,0.2]
labels = ['Music','Dance','Programming','Math']
explode = [0, 0.2, 0, 0]  # 用于突出圆饼图指定的一块数据,这里突出‘舞蹈’这部分
colors=['#9999ff','#ff9999','#7777aa','#2442aa','#dd5555'] # 可自定义颜色

plt.axes(aspect='equal')

ax = plt.subplot(1,1,1)
ax.pie(x=data,
        labels=labels,
        explode=explode,
        colors=colors,
        autopct='%.1f%%', # 自动添加百分比显示
        pctdistance=0.6,  # 百分比标签与圆心距离
        labeldistance = 1.1, # 每块扇形标签与圆心距离
        radius = 2, # 圆的半径
        wedgeprops = {'linewidth': 2, 'edgecolor':'pink'}, # 圆内外便捷的属性
        textprops = {'fontsize':19 ,'color':'k'}, # 饼图文本属性
        center = (0.2,0.2)) # 饼图中心点位置

plt.text(0.9, 2.5, 'pie',
         horizontalalignment='center',
         fontsize=25,
         transform = ax2.transAxes)    # 替代标题,使用title会遮挡

plt.savefig('pie', bbox_inches='tight') # 防止保存图片不完整
plt.show()

pie

散点图

x = np.arange(8)
y = np.array([27.0, 26.8, 26.5, 26.3, 26.1, 25.7, 25.3, 24.8])
plt.scatter(x, y)
plt.show()

scatter

向量图

x = np.linspace(0, 15, 11)
y = np.linspace(0, 10, 12)
x, y = np.meshgrid(x, y)
v1 = y * np.cos(x)
v2 = y * np.sin(x)
plt.quiver(x, y, v1, v2)
plt.show()

quiver

等高线图

plt.contour()函数可以绘制等高线图,x y z为绘制点,后面为等高线密度
plt.clabel()用于对等高线加上数值标记,并设置字体大小

x = np.arange(-2.0,2.0,0.01)
y = np.arange(-2.0,2.0,0.01)
X,Y = np.meshgrid(x,y)
def f(x,y):
    return (1-y**5+x**5)*np.exp(-x**2-y**2)

C = plt.contour(X,Y,f(X,Y),8)
plt.clabel(C,inline=1,fontsize=10)
plt.show()

contour_origional
此外,还可以通过contour函数的参数,给图片自定义颜色color='black',或使用颜色库中的渐变色cmap=plt.cm.hot
使用这两个参数后的图片:
contour_black contour_cmap
最后,我们还可以使用函数plt.colorbar()给图片添加颜色值

x = np.arange(-2.0,2.0,0.01)
y = np.arange(-2.0,2.0,0.01)
X,Y = np.meshgrid(x,y)
def f(x,y):
    return (1-y**5+x**5)*np.exp(-x**2-y**2)

C = plt.contour(X,Y,f(X,Y), 10)
plt.clabel(C,inline=1,fontsize=10)
plt.colorbar()    # 显示颜色值
plt.show()

contour_toolbar

极区图

极区图呈放射延伸状,每块会占一定的角度。其半径大小表示它代表的某一类数据的大小。其角度大小表示它所占总类别的比例。

plt.bar(角度, 半径, width=宽度, bottom= , color=颜色)

例如下面的例子

theta = np.arange(0.,2*np.pi,2*np.pi/8)
radii = np.array([4,7,5,3,1,5,6,7])
plt.axes([0.025,0.025,0.95,0.95],polar=True)
colors = np.array(['#4bb2c5','#c5b47f','#EAA228','#579575','#839557','#958c12','#953579','#4b5de4'])
bars = plt.bar(theta,radii,width=(2*np.pi/8),bottom=0.0,color=colors)
plt.show()

bar

三维绘图

使用projection='3d'来创建一个Axes3D对象

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
  • 绘制曲线和散点图

    # 绘制螺旋线
    zline = np.linspace(0, 15, 1000)
    xline = np.sin(zline)
    yline = np.cos(zline)
    ax.plot3D(xline, yline, zline, 'gray')
    
    # 绘制散点图
    zdata = 15 * np.random.random(100)
    xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
    ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
    ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap='Greens') # c为颜色深度渐变方向
    
    plt.show()  
  • 三维轮廓图
    coutour3D函数提供绘制三维轮廓图的方法,第四个参数50表示线的密度,set_*label函数为各个轴设置标签

      def f(x, y):
        return np.sin(np.sqrt(x ** 2 + y ** 2))
    x = np.linspace(-6, 6, 30)
    y = np.linspace(-6, 6, 30)
    X, Y = np.meshgrid(x, y)
    Z = f(X, Y)
    
    fig = plt.figure()
    ax = plt.axes(projection='3d')
    
    ax.contour3D(X, Y, Z, 50, cmap='binary')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    plt.show()

    3d_countour
    若视图不直观,可以使用ax.view_init()函数修改视角

  • 表面三角测量
    使用函数plot_wireframe绘制线框图

    fig = plt.figure()
    ax = plt.axes(projection='3d')
    ax.plot_wireframe(X, Y, Z, color='black')
    ax.set_title('wireframe')
    plt.show()

    wireframe

  • 表面采样
    也可以对我们的三维散点图构成图形的表面进行采样

    ax = plt.axes(projection='3d')
    ax.plot_surface(X, Y, Z, rstride=1, cstride=1,cmap='viridis', edgecolor='none')
    ax.set_title('surface')
    plt.show()

    surface

Clone this wiki locally