• Matplotlib——中级


     关于Matplotlib的愚见

    初级中,我只是简单介绍了Matplotlib的使用方法,在中级部分,我系统地说一下我总结的内容。

     

    上图是我画的关于Matplotlib几个对象之间的关系图。它们都来自于一个叫做Artist的基类。我们知道绘制图的基础是Canvas,它是我们真正进行绘图的后端。Artist只是在程序逻辑上的绘图,它必须连接后端绘图程序才能真正在屏幕上绘制出来(或者保存为文件)。我们可以将canvas理解为绘图的物理(或者说硬件)实现。对于每个Artist类的对象,都有findobj()方法,来显示该对象所包含的所有下层对象。

     Artist对象的所有属性都通过相应的get_*和set_*函数来读写。在后面的例子中,很多都不是对fig的操作,而是对ax的操作,这里要记住这种方法。

    fig.set_alpha(0.5*fig.get_alpha())

     如果要同时给多个属性进行设置的话,可以使用set函数: 

    fig.set(alpha = 0.5, zorder=2)

     使用matplotlib.pyplot.getp 函数则可以方便地输出Artist对象的所有属性名和值。

    plt.getp(fig.patch)

    生成多张画布

    比如

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-3, 3, 10)
    print(x)
    y = x*2+1
    z = x**2
    
    plt.figure()
    plt.plot(x, y)
    
    plt.figure()
    plt.plot(x, z)
    
    plt.show()

     运行效果为:

     和   

    如果不写的话,默认是从1开始算。我们也可以在里面指定参数,用来给这个画布编号,比如:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-3, 3, 100)
    y = x*2+1
    z = x**2
    
    plt.figure()
    plt.plot(x, y)
    
    plt.figure(num=3, figsize=(8, 5))
    plt.plot(x, z)
    
    plt.show()

     运行效果为:

      和   

    坐标轴常用设置

    • xlim、ylim方法设置坐标轴刻度取值范围
    • xlabel、ylabel方法设置x轴和y轴的标题
    • xticks,yticks方法设置x,y轴的刻度标签值

    例子:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-3, 3, 100)
    y = x*2+1
    
    plt.figure(1)
    plt.plot(x, y)
    
    plt.figure(2)
    plt.plot(x, y)
    
    # 设置坐标轴取值范围
    plt.xlim((-2, 2))
    plt.ylim((0, 3))
    
    # 设置坐标轴标题
    plt.xlabel("我是横坐标")
    plt.ylabel("我是纵坐标")
    
    # 设置刻度标签
    new_ticks = np.linspace(-1, 4, 6)
    plt.xticks(new_ticks)    # 将原有x轴刻度标注修改,图也会随着坐标改变而改变。
    plt.yticks([1, 2, 3],
              ["", r"$I am middle$", ""])     # 用第二个参数的值一一替换第一个参数的值。
    
    
    plt.show()

     运行效果为:

      和   

    坐标轴边框设置及位置移动

    这里我们需要认识的是:gca,它的意思是get current axis(获取当前轴)。

    获取了当前绘图区(轴)之后我们再通过ax.spines对其进行操作,spines是脊柱的意思。

    具体的操作如下例:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-3, 3, 100)
    y = x*2+1
    
    plt.figure(1)
    plt.plot(x, y)
    
    plt.figure(2)
    plt.plot(x, y)
    
    # 去掉上和右边的边框线
    ax = plt.gca()           # 获取当前绘图区
    ax.spines["right"].set_color("none")
    ax.spines["top"].set_color("none")
    
    # 更改坐标轴位置
    ax.xaxis.set_ticks_position("bottom")     # 因为绘制的图形中,上下都算是坐标轴,我们如果要绘制坐标系的话需要指定其中一个为坐标轴,这里我们是将下坐标轴来作为X轴。
    ax.yaxis.set_ticks_position("left")     # 同上,用左轴作为Y轴。
    ax.spines["bottom"].set_position(("data", 0))  # data表示用值来选择,这个句话的意思就是用X坐标轴上值为0的点作为坐标系原点。"data"只是一个参数,还有outward,axes等参数,它们都有不同的意义。
    ax.spines["left"].set_position(("data", 0))   # 同上
    
    plt.show()

      运行结果为:

      和     

    图例的设置

    在初级,我们说过简单的设置图例,这里我们在进行一些拓展的说明。

    例子:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-3, 3, 100)
    y = x*2+1
    z = x**2
    
    plt.figure(1)
    L1, = plt.plot(x, y, label="$x*2+1$")  # L1后面的逗号是matplotlib特殊的写法
    L2, = plt.plot(x, z, label="$x^2$")
    
    plt.legend(handles=[L1], labels=["a", "b"], loc="best") # handles是用来控制放入图例的内容。labels是用来给handles对应的图修改图例名。
    
    plt.show()

     运行结果为:

    在图片中添加注解

    在讲解给图片添加注解之前呢,我们需要认识一下scattter函数,我们在绘制图像的时候使用的是plot,它是线的形式,如果我们使用scatter的话,它就会用点的形式来绘制。 

     下面是示例代码:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-3, 3, 100)
    y = x*2+1
    
    plt.figure(1)
    plt.plot(x, y)
    
    plt.figure(2)
    plt.plot(x, y)
    
    # 去掉上和右边的边框线
    ax = plt.gca()           # 获取当前绘图区
    ax.spines["right"].set_color("none")
    ax.spines["top"].set_color("none")
    
    # 更改坐标轴位置
    ax.xaxis.set_ticks_position("bottom")     # 因为绘制的图形中,上下都算是坐标轴,我们如果要绘制坐标系的话需要指定其中一个为坐标轴,这里我们是将下坐标轴来作为X轴。
    ax.yaxis.set_ticks_position("left")     # 同上,用左轴作为Y轴。
    ax.spines["bottom"].set_position(("data", 0))  # data表示用值来选择,这个句话的意思就是用X坐标轴上值为0的点作为坐标系原点。"data"只是一个参数,还有outward,axes等参数,它们都有不同的意义。
    ax.spines["left"].set_position(("data", 0))   # 同上
    
    # 设置标注
    x0 = 1 
    y0 = 2*x0 + 1
    plt.scatter(x0, y0, s=50, color="b")      # 设置要标注的点,scatter和plot函数一样可以绘制图形,不过它是用点构成的图形。其中s是控制大小,color是控制颜色。
    plt.plot([x0, x0], [y0, 0], "k--", lw=1)    # 设置一个黑色的虚线。
    
    plt.annotate(r'$2x+1=%s$' % y0, xy=(x0, y0), xycoords='data', xytext=(+30, -30),
                 textcoords='offset points', fontsize=16,
                 arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=.2"))
    """
    下面是annotate中每个参数设置的意思:
    plt.annotate(r"$2x+1 = %s$" % y0,  # 标注的文字描述
                  xy=(x0, y0),           # xy是设置要标注的点。
                  xycoords="data",       # xycoords表示前面xy设置的内容以"data"的值为基准。
                  xytext=(+30, -30),      # 标注信息在要标注的点的横坐标加30,纵坐标减30的位置显示。
                  textcoords="offset point",   # xtext设置的内容以"offset point",也就是偏移量为基准。
                  fontsize=16,         # 设置字体的大小
                  arrowprops=dict(arrowstyle="->", connectionstyle="arc3, rad=.2")  # 设置箭头。arrowstyle的设置表示使用箭头,connectionstyle是用来设置弧度的。
                 )      
    """
    
    plt.text(-3.7, 3, r'$This is the some text. mu sigma_i alpha_t$',
             fontdict={'size': 16, 'color': 'r'})
    
    """
    下面是text中每个参数设置的意思:
    plt.text(-3.7, 3,      # 文字显示的位置
            r'$This is the some text. mu sigma_i alpha_t$',    # 显示的文字
             fontdict={'size': 16, 'color': 'r'})           # 文字的格式
    
    """
    
    plt.show()

     运行结果如下:

      和   

    当线遮挡刻度标注解决办法

    示例代码:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-3, 3, 50)
    y = 0.1*x
    
    plt.figure()
    # 在 plt 2.0.2 或更高的版本中, 设置 zorder 给 plot 在 z 轴方向排序
    plt.plot(x, y, linewidth=10, zorder=1)
    plt.ylim(-2, 2)
    ax = plt.gca()
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data', 0))
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data', 0))
    
    for label in ax.get_xticklabels() + ax.get_yticklabels():
        label.set_fontsize(12)    # 设置字体大小
    
        label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.7, zorder=2))
        """
        set_bbox的参数说明:
         label.set_bbox(dict(facecolor='white',    # 背景颜色
                         edgecolor='None',    # 边框
                         alpha=0.7,        # 背景透明度
                         zorder=2))    # 在 plt 2.0.2 或更高的版本中, 设置 zorder 给 plot 在 z 轴方向排序
        """
    plt.show()

     运行结果:

     同画布绘制多图

    方式1:使用subplot来绘制

    在初级中,我们说过我们画一个图是要在一个画布上,我们画的图在Matplotlib中被称为轴或者绘图区,一个画布中可以包含多个绘图区,每个绘图区都拥有自己坐标系统的绘图区域。我们可以通过subplot()函数来快速绘制有多个绘图区的画布。

    它的格式为:

    plt.subplot(numRows, numCols, plotNum)

     subplot将整个绘图区域划分为numRows行和numCols列个区域,然后按照从左到右,从上到下的顺序对每个子区域进行编号,如下图所示。

    在使用的时候,有的人可能会看到subplot(324)这样的设置,这样也是正确的写法,它等效于subplot(3, 2, 3)。如果numRows、numCols、plotNum这三个数都小于10的话,可以把它们缩写为一个整数。

    如果新建的轴和之前的轴位置重叠的话,原来的轴会被覆盖。

    使用例子如下:

    import matplotlib.pyplot as plt
    plt.figure()
    
    plt.subplot(2, 2, 1)
    plt.plot([0, 1], [0, 1])
    
    plt.subplot(2, 2, 2)
    plt.plot([0, 1], [0, 2])
    
    plt.subplot(223)
    plt.plot([0, 1], [0, 3])
    
    plt.subplot(224)
    plt.plot([0, 1], [0, 4])
    
    plt.show()

     运行效果为:

    我们还可以自定义它们的跨列显示

    import matplotlib.pyplot as plt
    plt.figure()
    
    plt.subplot(2, 1, 1)        
    plt.plot([0, 1], [0, 1])
    
    plt.subplot(2, 3, 4)
    plt.plot([0, 1], [0, 2])
    
    plt.subplot(235)
    plt.plot([0, 1], [0, 3])
    
    plt.subplot(236)
    plt.plot([0, 1], [0, 4])
    
    plt.show()

     运行代码如下:

     

    说明:

    使用subplot是比较别扭的,要大概了解它的绘制顺序。在上面例子中,

    (2, 1, 1),第一个参数表示figure分为两行,第二个参数表示分为一列,第三个表示它使用第一个图绘制。

    (2, 3, 4),第一个参数表示figure分为两行,第二个参数表示分为三列,第三个表示它使用第四个图绘制(因为第一行是跨3列,所以这个是从第四个开始计算)。(2, 3, 5)和(2, 3, 6)同理。

     不同figure切换加figure切分的例子:

    import numpy as np
    import matplotlib.pyplot as plt 
    
    plt.figure(1)
    plt.figure(2)
    ax1= plt.subplot(221)
    ax2 = plt.subplot(222)
    ax3 = plt.subplot(212)
    x = np.linspace(0, 3, 100)
    for i in range(5):
        plt.figure(1)
        plt.plot(x, np.exp(i*x/3))
        plt.sca(ax1)
        plt.plot(x, np.sin(i*x))
        plt.sca(ax2)
        plt.plot(x, np.cos(i*x))
        plt.sca(ax3)
        plt.plot(x, np.exp(i*x/3))
    plt.show()

     它的效果如图:

     从上面的例子中我们可以看出:使用subplot()会返回它所创建的绘图区,通过变量保存后,我们可以使用sca()函数交替让它们成为当前绘图区,然后调用plot()函数在这个绘图区里面绘制图形。如果有多个画布,我们可以用figure()函数来指定一个画布。如果这个画布存在则将该画布变为当前画布,如果不存在则创建一个对应的画布。

    方式2:使用subplot2grid来绘制

    subplot2grid使用起来要比第一种subplot的方式要更直观和清晰些。我们来看看例子:

    import matplotlib.pyplot as plt
    
    plt.figure()
    ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3, rowspan=1)   # 第一个参数是整个figure分为几个块,第一个为行,第二个为列;第二个参数为这个图形的起始位置,位置是从0开始计算的;第三个和第四个分别设置这个图形占据几列和几行。
    ax1.plot([1, 2], [2, 2])
    ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
    ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
    ax4 = plt.subplot2grid((3, 3), (2, 0))
    ax5 = plt.subplot2grid((3, 3), (2, 1))

     运行结果:

    方式3:使用gridspec来绘制

    使用它之前我们要先导入:

    import matplotlib.gridspec as gridspec

     让我们再看看实际的使用:

    import matplotlib.pyplot as plt
    import matplotlib.gridspec as gridspec
    
    plt.figure()
    gs = gridspec.GridSpec(3, 3) # 将一个figure分成3*3的格子。
    
    ax1= plt.subplot(gs[0, :])     # 占第0行和所有列
    ax2 = plt.subplot(gs[1, :2])    # 占第1行和第2列前的所有列
    ax3 = plt.subplot(gs[1:, 2])   # 占第1行后的所有行和第2列
    ax4 = plt.subplot(gs[-1, 0])    # 占倒数第1行和第0列
    ax5 = plt.subplot(gs[-1, -2])  # 占倒数第1行和倒数第2列.

     运行结果:

    方式4:使用subplots来绘制

    注意,这个和第一种方法不同,第一种创建方式我们使用的是subplot,这里我们使用的是subplots。

     使用例子:

    import matplotlib.pyplot as plt
    
    f,((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex=True, sharey=False) 
    plt.tight_layout()    # 不加会紧凑显示
    ax1.plot([1, 2], [2, 2])   # ax1中绘制图像。
    plt.show()
    
    """
    说明:
    使用plt.subplots建立一个2行2列的图像窗口,
    sharex=True表示共享x轴坐标, 
    sharey=True表示共享y轴坐标。
    ((ax11, ax12), (ax13, ax14))表示第1行从左至右依次放ax1和ax2, 第2行从左至右依次放ax3和ax4.
    """

     运行效果:

     绘制图内图

    代码:

    # 导入pyplot模块
    import matplotlib.pyplot as plt
    
    # 初始化figure
    fig = plt.figure()
    
    # 创建数据
    x = [1, 2, 3, 4, 5, 6, 7]
    y = [1, 3, 4, 2, 5, 8, 6]
    left, bottom, width, height = 0.1, 0.1, 0.8, 0.8    # 4个值都是占整个figure坐标系的百分比。在这里,假设figure的大小是10x10,那么大图左边距为1,底边距为1,宽8,高8的坐标系内。
    
    # 绘制外围图
    ax1 = fig.add_axes([left, bottom, width, height])
    ax1.plot(x, y, 'r')
    ax1.set_xlabel('x')
    ax1.set_ylabel('y')
    ax1.set_title('title')
    
    # 绘制内图
    left, bottom, width, height = 0.2, 0.5, 0.3, 0.3
    ax2 = fig.add_axes([left, bottom, width, height])   # 假设figure的大小是10x10,那么大图左边距为2,底边距为5,宽3,高3的坐标系内。
    ax2.plot(y, x, 'b')
    ax2.set_xlabel('x')
    ax2.set_ylabel('y')
    ax2.set_title('title inside 1')

     运行结果为:

  • 相关阅读:
    我的DBDA类文件
    登录时的验证码怎么写?
    phpcms 制作简单企业站的常用标签
    HTML 基础知识
    目标
    split函数的实现
    myString操作符重载
    cout中的执行顺序_a++和++a
    二叉树的层次遍历法
    树的前中序遍历_求后续遍历
  • 原文地址:https://www.cnblogs.com/kuxingseng95/p/10026895.html
Copyright © 2020-2023  润新知