Matplotlib简介
Matplotlib 是 Python 从 Matlab 迁移过来的一个 2D 绘图库,它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有出版品质的图形,通过几行代码,就能开发出直方图、饼状图、散点图、三维图等各式各样的专业图表,具有极强的自定义性和可扩展性。下面是 Matplotlib 官网 的几个示例图表:
同时由于 Matplotlib 是基于 NumPy (一个科学计算包)和 tkinter (一个图形框架) 二次开发的,Matplotlib 在科学计算结果可视化领域越来越受到欢迎。
Matplotlib组成
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 库;
一般有下面两种办法:
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() 之后,其效果图如下:
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 np
import matplotlib.pyplot as plt
import mpl_toolkits.axisartist as axisartist
def 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)]))
其中函数表达式是以 y = 1/3*x**3-3/2*x**2+2*x
为例的,只需在代码的最后一行按照格式修改即可。
可视化结果
如此一来,当我们想快速查看一个复杂函数时的变化趋势时,不需要写任何绘图代码就能快速绘图,只需要将函数表达式按照上述格式写出即可,而且可以一眼看出函数的极值点和极值,下一步的工作就是把最值,函数凹凸性功能实现。