Matplotlib 实战:写一个任意函数极值可视化脚手架

640?wx_fmt=png


作者:月小水长,Java、Python、Android coder。

 
 


Matplotlib简介


Matplotlib 是 Python 从 Matlab 迁移过来的一个 2D 绘图库,它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有出版品质的图形,通过几行代码,就能开发出直方图、饼状图、散点图、三维图等各式各样的专业图表,具有极强的自定义性和可扩展性。下面是 Matplotlib 官网 的几个示例图表:


640?wx_fmt=png



640?wx_fmt=png


同时由于 Matplotlib 是基于 NumPy (一个科学计算包)和 tkinter (一个图形框架) 二次开发的,Matplotlib 在科学计算结果可视化领域越来越受到欢迎。


Matplotlib组成


 
 

不得不说的 backend


backend 是为Matplotlib中的绘图功能做幕后工作的,对应的frontend 指的就是你编辑的绘图命令。通过设置 backend 可以使得 Matplotlib 适应不同的应用场景,或者说输出形式,例如:Python 中的命令行模式下弹出的figure,图形界面的工具 wxPython中 嵌入的 Matplotlib,网页应用服务,批处理脚本生成可视化数据等。


backend 可以分为两类:交互式的,包括命令行以及图形界面的集成开发环境;非交互式的,比如输出图片文件(格式为 PNG,JPG,PDF等)的。

常见的 backend 类型:


不可交互型可交互型
AGG:渲染为 png 文件Qt5Agg:使用 Qt5 渲染,IPython 中可使用 %matplotlib qt5
PS:渲染为 ps 文件macosx:使用 Cocoa 画布渲染,Ipython 中可使用 %matplotlib osx
PDF:渲染为 pdf 文件nbAgg:Jupyter Notebook 中使用的 backend,Jupyter 中使用 %matplotlib notebook 来激活
SVG:渲染为 svg 文件WXAgg:使用 wxWidgets 库来渲染,Ipython 中可使用 %matplotlib wx


假如我们要激活 WXAgg 渲染模式,可以使用


import matplotlib      
matplotlib.use('WXAgg')


注意激活语句最后紧跟着导入语句,中间不能有 plt.plot() 之类的绘图语句


Matplotlib基本用法


由于Matplotlib是第三方库,请先确保你的电脑上已经安装成功 Matplotlib 库;


一般有下面两种办法:

  1. 在命令行下输入: pip install matplotlib

  2. 通过下载whl文件安装,可以参考:

https://blog.csdn.net/ygdxt/article/details/80517024


导入


根据开源社区的习惯,一般这样导入

import matplotlib.pyplot as plt

创建画布

plt.figure()

如果在 plt.figure() 后直接 plt.show(),将弹出一个空白图表的画布窗口


具体绘图


Matplotlib 的绘图是面向过程的,具体的绘图操作差不多都在这一步完成,比如我想在一个子图中绘制出 sin(x) 和 cos(x) ,控制代码如下:


x = np.arange(0,np.pi*2,0.01)y1 = np.sin(x)y2 = np.cos(x)#下面两句代码可以简化为一句代码:#plt.plot(x,y1,x,y2)plt.plot(x,y1)plt.plot(x,y2)


plt.show() 之后,其效果图如下:


640?wx_fmt=png


plot() 函数只是 Matplotlib 库中最简单的绘图函数,除了横坐标x、纵坐标y外,它还可以通过关键字参数c(color) 控制线条的颜色,比如 plt.plot(x,y1,c="y") 可以使上图中曲线 sin(x) 的颜色变成黄色,通过关键字参数s(size) 控制线条的粗细等,有具体需求的时候可以查对应的的 API 手册。

pyplot 模块中其他一些重要的绘制函数列表如下:


名称功能
plt.hist()画直方图
plt.scatter()画散点图
plt.bar()画柱形图
plt.annotate()给图像加注释

注:绘图部分由于 API 过多,在此仅列出基础函数,后面我会视情况专门出一个针对此部分的教程

显示

plt.show()

将整个画布以及上面的子图显示出来。



用 Matplotlib 解决一个实际问题


假设我们现在要解决一个需求

求任意多项式函数的极值并将计算结果可视化

全部代码

Tips:听说看代码时认真看注释,效果更好哦。

# -*- coding: utf-8 -*-# author:           inspurer(月小水长)# pc_type           lenovo# create_time:      2019/5/26 13:19# file_name:        my_differ.py# github            https://github.com/inspurer# 微信公众号         月小水长(ID: inspurer)from sympy import *import numpy as npimport matplotlib.pyplot as pltimport mpl_toolkits.axisartist as axisartistdef count_extreme(args):    # 声明符号 x    sign_x = Symbol("x")    # 声明 y 符号表达式    sign_y = 0    # 数值 x    num_x = np.arange(-5,5,0.01)    # print(num_x,num_x.shape)    # num_y = np.zeros((1,len(num_x)))    num_y = np.zeros(len(num_x))    # print(num_y, num_x.shape)    for item in args:        sign_y += item[0]*sign_x**item[1]        num_y += item[0]*num_x**item[1]    # y 对 x 求导    dy = diff(sign_y,sign_x)    # 返回导函数的零点    extreme_x_list = solve(dy,sign_x)    if len(extreme_x_list)==0:        return "no extrem vaule"    print(extreme_x_list)    # 声明定义域    fig = plt.figure()    # 使用axisartist.Subplot方法创建一个绘图区对象ax    ax = axisartist.Subplot(fig, 111)    # 将绘图区对象添加到画布中    fig.add_axes(ax)    ## 引入 axisartist 会再次造成乱码,可以通过annotate解决    plt.annotate('X轴', xy=(max(num_x),0), xycoords='data',xytext=(0,5),                 textcoords='offset points', fontsize=16, fontproperties='SimHei')    plt.annotate('Y轴', xy=(0,max(num_y)), xycoords='data',xytext=(5,0),                 textcoords='offset points', fontsize=16, fontproperties='SimHei')    # plt.xlabel("X轴",fontproperties='SimHei',fontsize=14)    # # 标签里面必须添加字体变量:fontproperties='SimHei',fontsize=14。不然中文显示可能会乱码    # plt.ylabel("Y轴",fontproperties='SimHei',fontsize=14)    # sympy 转成 str    plt.title(str(sign_y))    plt.plot(num_x,num_y)    for i,extreme_x in enumerate(extreme_x_list):        extreme_y = sign_y.evalf(subs={sign_x:extreme_x})        # if the slove is not real        # the class is sympy,core.numbers.Zero        if (isinstance(extreme_y,numbers.Zero)):            return "extreme value is not real"        p = plt.scatter(extreme_x,extreme_y,s=50,c="red")        #  xytext -- 为注解内容位置坐标,当该值为None时,注解内容放置在xy处        #  xycoords and textcoords 是坐标xy与xytext的说明,若textcoords=None,则默认textNone与xycoords相同,        #  若都未设置,默认为data,        #  arrowprops 用于设置箭头的形状,类型为字典类型        plt.annotate('y(%.6s)=%.6s ' % (extreme_x,extreme_y), xy=(extreme_x, extreme_y), xycoords='data', xytext=((-1)**(i+1)*30, (-1)**(i+1)*30),                     textcoords='offset points', fontsize=16,fontproperties='SimHei',                     arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=.2"))        plt.legend(handles=[p], labels=['points of extreme value'],loc='best')        # 通过set_visible方法设置绘图区所有坐标轴隐藏        ax.axis[:].set_visible(False)        #ax.new_floating_axis代表添加新的坐标轴        ax.axis["x"] = ax.new_floating_axis(0, 0)        #给x坐标轴加上箭头        ax.axis["x"].set_axisline_style("->", size=1.0)        #添加y坐标轴,且加上箭头        ax.axis["y"] = ax.new_floating_axis(1, 0)        ax.axis["y"].set_axisline_style("-|>", size=1.0)        #设置x、y轴上刻度显示方向        ax.axis["x"].set_axis_direction("top")        ax.axis["y"].set_axis_direction("right")        # 我们先把原始的如上图的所有坐标轴隐藏,即长方形的四个边。        #        # 然后用ax.new_floating_axis在绘图区添加坐标轴x、y,这里的ax.new_floating_axis(0, 0),第一个0代表平行直线,第二个0代表该直线经过0点。同样,ax.axis[        #     "y"] = ax.new_floating_axis(1, 0),则代表竖直曲线且经过0点。        #        # 再次,x.axis["x"].set_axisline_style("->", size=1.0)        # 表示给x轴加上箭头,"->"        # 表示是空箭头,size = 1.0        # 表示箭头大小。ax.axis["y"].set_axisline_style("-|>", size=1.0)        # 中        # "-|>"        # 则是实心箭头。        #        # 最后,设置x、y轴上刻度显示方向,对于x轴是刻度标签在上面还是下面,y轴则是刻度标签在左边还是右边。    plt.grid(True)    plt.grid(color='black', linestyle='--')  # 修改网格颜色,类型为虚线,网格是跟坐标刻度来的    plt.show()if __name__ == "__main__":    # examples    # wanted: 1/3*x**3-3/2*x**2+2*x    # args: [(1/3,3),(-3/2,2),(2,1)]    print(count_extreme([(1/3,3),(-3/2,2),(2,1)]))


函数计算用到了第三方库 sympy ,感兴趣的同学可以先学习,有不懂的地方可以通过留言;否则可以忽略,我们的注意力放在绘图部分


其中函数表达式是以 y = 1/3*x**3-3/2*x**2+2*x 为例的,只需在代码的最后一行按照格式修改即可


可视化结果


640?wx_fmt=png


如此一来,当我们想快速查看一个复杂函数时的变化趋势时,不需要写任何绘图代码就能快速绘图,只需要将函数表达式按照上述格式写出即可,而且可以一眼看出函数的极值点和极值,下一步的工作就是把最值,函数凹凸性功能实现。


640?wx_fmt=png

▼ 点击成为社区注册会员          「在看」一下,一起PY!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值