python绘图库Matplotlib基础

Matplotlib是一个Python语言的2D绘图库,它支持各种平台,并且功能强大,能够轻易绘制出各种专业的图像。本文是对它的一个入门教程。

Matplotlib是一个Python语言的2D绘图库,它支持各种平台,并且功能强大,能够轻易绘制出各种专业的图像。本文是对它的一个入门教程。

运行环境

由于这是一个Python语言的软件包,因此需要你的机器上首先安装好Python语言的环境。关于这一点,请自行在网络上搜索获取方法。

关于如何安装Matplotlib请参见这里:Matplotlib Installing

笔者推荐大家通过pip的方式进行安装,具体方法如下:
sudo pip3 install matplotlib

本文中的源码和测试数据可以在这里获取:matplotlib_tutorial


这些教程涵盖了使用 Matplotlib 创建可视化的基础知识,以及有效使用包的一些最佳实践。

可以简单的绘制出直方图,功率图,条形图,误差图,散点图等。https://matplotlib.org/tutorials/introductory/sample_plots.html  示例图库
https://matplotlib.org/gallery/index.html 缩略图库

Matplotlib 有大量的代码库,可能会让许多新用户却步,然而 Matplotlib 的大部分内容只需要一个相当简单的概念框架和一些重要的知识点就可以理解。

绘图需要在一定范围的层次上进行操作,从最一般的层次(contour this 2-D array )到最具体的层次(color this screen pixel red )。绘图包的目的是通过所有必要的控制。即:大部分时间使用相对高级的命令,并且在需要时仍然能使用低级命令—帮助尽可能容易地完成可视化数据。

因此 Matplotlib 中的所有内容都被组织在一个层次结构中,位于层次结构顶部的是 Matplotlib “状态机环境”,由 Matplotlib.pyplot 模块提供。在这个级别上使用简单的函数向当前图形的当前轴添加绘图元素(线条、图像、文本等)。

Pyplot 的状态机环境的行为类似于 MATLAB,对于具有 MATLAB 经验的用户来说应该是最熟悉的。

层次结构的下一个级别是面向对象接口的第一个级别,其中 pyplot 仅用于图形创建等少数函数,用户显示创建并跟踪图形和轴对象。在这个级别上用户使用 pyplot 创建图形,并通过这些图形创建一个或多个轴对象,然后这些轴对象用于大多数绘图操作。

Parts of a Figure(图中的部件):

Figure(图):
完整的一个图。该图保留追踪到的所有子 轴域 、一些 Matplotlib 中特有的 Artist(艺术家对象。如:标题,角色说明等)和 canvas 。(不要过于担心 canvas ,这一点非常重要,虽然实际上是这个对象绘制出了你的图,但是作为用户来说或多或少是不可见的)。一个图形可以有任意数量的 轴域 ,但为了有用,至少应该有一个 轴域 。

创建一个新图形最简单的方法是用 pyplot:

import matplotlib.pyplot as plt;

fig = plt.figure() # an empty figure with no axes
fig.suptitle('No axes on this figure') # Add a title so we know which it is

fig, ax_lst = plt.subplots(2, 2) # a figure with a 2x2 grid of Axes

plt.show();

Axes(轴域):
所谓的“图”,它的区域是图像和数据的 作用域 。一个给定的图形可以包含多个轴域,但是一个给定的轴域对象只能在一个图中。轴域包含两个(或三个 3D 情况下)轴线对象(注意:Axes(轴域)金额 Axis(轴线)之间的区别),它们(指轴域)负责数据范围(数据范围也可以通过 set_xlim() 和 set_ylim() 轴域方法进行控制)。每个轴域都有一个标题(通过 set_title() 设置)、一个 x-label (通过 set_xlabel() 设置)和 y-label 通过 set_ylabel() 设置。Axes 类及其成员函数是使用 OO 接口的主要接口点。

Axis(轴线):
它们类似 number-line-like 对象。负责设置图形限制并生成刻度(轴线上的标记)和ticklael(刻度标签)。刻度的位置由 Locator 对象确定,刻度标签的线的格式由 Formatter 对象设置。正确的 Locator 和 Formatter 程序组合可以很好地控制刻度位置和标签。

Artist(艺术家):
基本上,在图形上看到的所有东西都是艺术家(Artistd 对象)(甚至包括 Figure,Axes,Axis 对象等)。这包括 Text(文本)对象,Line2D 对象, collection(集合) 对象,Patch(修补)对象等等(你懂的)。当图形绘制时,所有的 Artist(艺术家)被画到 Canvas(画布)上。大多数 Artist(艺术家)都绑定在一个 Axes(轴域)对象上,这样的 Artist(艺术家)不能被多个 Axes(轴域)对象共享,也不能从一个 Axes(轴域)对象移动到另一个 Axes(轴域)对象上。

plotting (绘图)函数所支持的数据类型:
所有 plotting 函数都支持 np.array 或 np.ma.masked_array 数据。array-like 形式的对象和
pandas 数据类有可能支持。最好在图像绘制前将数据对象转换为 np.array 对象。

Matplotlib、pyplot 和 pylab 之间的关系:
Matplotlib 是整个包;Matplotlib.pyplot 是 Matplotlib 中的一个模块;pylab 是与 Matplotlib 一起安装的模块。
Pyplot 为底层 绘图库对象 提供 state-machine 接口。state-machine 会自动和以用户无感的方式创建 Figures(图)对象 和 axes (轴域),以实现所需的绘图操作。例如:

import matplotlib.pyplot as plt;
import numpy as np;

x = np.linspace(0, 2, 100);

plt.plot(x, x, label = 'linear');
plt.plot(x, x**2, label = 'quadratic');
plt.plot(x, x**3, label = 'cubic');

plt.xlabel('X 标注');
plt.ylabel('Y 标注');

plt.title('标题');

plt.legend();

plt.show();

对 plt.plot() 的第一个调用将自动创建 Figure 和 Axes 对象,以实现所需的绘图。对 plt.plot() 后续的调用会重复使用当前 Axes 对象,并每次添加一行。设置 title 标题、legend 图例等,都会使用当前 Axes 对象,设置相应的 Artist(艺术家)。

Pylab 是一个便捷的模块,它在一个命名空间中被批量导入 Matplotlib.pyplot(用于绘图)和 Numpy(用于数学和数组)。Pylab 是不推荐使用的,并且由于命名空间污染强烈禁止使用它。请使用 pyplot 替代。

对于 non-interactive(非交互式)绘图,建议使用 pyplot 创建图形,然后使用 OO 接口进行绘图。

Coding Styles (编码风格)
在查看此文档和示例时,您将发现不同的编码风格和使用模式。这些风格是完全有效的,并有它们的优点和缺点。几乎所有的例子都可以转换成另一种风格,并得到相同的结果。唯一需要注意的是要避免为自己的代码混合编码风格。

注意
Matplotlib 的开发人员必须遵循特定的风格和指导方针。参见 Matplotlib 开发者指南

在不同的风格中,有两种是官方支持的。因此这些是使用 Matplotlib 的首选方法。

对于 pyplot 风格,脚本导入通常是:

import matplotlib.pyplot as plt 
import numpy as np

然后调用,例如,np.arange、np.zeros、np.pi、plt.figure、plt.plot、plt.show 等等。使用 pyplot 接口创建图形,然后使用 object 方法创建其余的图形:

x = np.arange(0, 10, 0.2)
y = np.sin(x)
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()

那么,在例子中为什么不使用 Matlab 风格(它依赖于全局变量和浅的命名空间)而使用另外的方式?对于像这个例子非常简单,仅用在学术(学习)上;用复杂的风格编程,会更清楚的知道程序执行的来龙去脉和发生了什么。对复杂程序来说,这种明确性和清晰性会越来越重要,更丰富和更完整的面向对象接口可能会使程序更容易编写和维护。

很多情况下,会发现自己一遍又一遍地绘制相同的图表,但使用的数据集不同,这导致需要编写专门的函数来绘制图表。 函数如下:

import matplotlib.pyplot as plt;
import numpy as np;

def my_plotter(ax, data1, data2, param_dict):
"""
A helper function to make a graph

Parameters
----------
ax : Axes
The axes to draw to

data1 : array
The x data

data2 : array
The y data

param_dict : dict
Dictionary of kwargs to pass to ax.plot

Returns
-------
out : list
list of artists added
"""
out = ax.plot(data1, data2, **param_dict)
return out

# which you would then use as:

data1, data2, data3, data4 = np.random.randn(4, 100)
fig, ax = plt.subplots(1, 1)
my_plotter(ax, data1, data2, {'marker': 'x'})
plt.show()

如果想同时生成两个图:

fig, (ax1, ax2) = plt.subplots(1, 2)
my_plotter(ax1, data1, data2, {'marker': 'x'})
my_plotter(ax2, data3, data4, {'marker': 'o'})

当然,对于这个例子来说,这样的编程风格麻烦了,但是一旦图表变得稍微复杂一些,风格说带来的回报就体现出来了。

Backends(后端)

什么是后端?
网站和邮件列表中的许多文档都提到了“Backends(后端)”,许多新用户对这个术语感到困惑。Matplotlib 针对许多不同的案例和输出格式。有些从 python shell 交互式地使用 Matplotlib 当输入命令时,会弹出绘图窗口。有些运行 Jupyter 笔记本并绘制内联图以便快速进行数据分析。还有些将 Matplotlib 嵌入到图形界面中,比如 wxpython 或 pygtk,以构建富应用程序。也可以批处理脚本中使用 Matplotlib 从数据模拟中生成 postscript 图像,更可以运行 web 应用服务器来动态提供图形。

为了支持所有案例,Matplotlib 可以针对不同的输出,这些功能中的每一个都称为后端(也就是 Matplotlib 开发者的代码),反之“前端”是面向用户的代码,即:绘图代码,而“后端”完成所有在幕后制作图形的工作。有两种类型的后端:用户界面后端(用于 pygtk、wxpython、tkinter、qt4 或 macosx;也称“交互式后端”)和用于生成图像文件的硬拷贝后端(PNG、SVG、PDF、PS;也称为“非交互式后端”)。

有四种配置后端的方法。如果它们彼此冲突,可以使用下面列表中最后提到的方法,例如调用 use() 将覆盖 Matplotlibrc 中的配置。

1:Matplotlibrc 文件中的后端参数(参照样式表和 rcParams 自定义 Matplotlib) :

backend : WXAgg   # use wxpython with antigrain (agg) rendering 

2:为当前 shell 或单个脚本设置 MPLBACKEND 环境变量。 在 Unix 上:

export MPLBACKEND=module://my_backend 
python simple_plot.py
MPLBACKEND="module://my_backend" python simple_plot.py

在 Windows 上,只有样例可以:

set MPLBACKEND=module://my_backend
python simple_plot.py

设置这个环境变量将覆盖任何 Matplotlibrc 中的后端参数,即使当前工作目录中有 Matplotlibrc。因此在全局设置 MPLBACKEND,例如在 .bashrc 和 .profile,可能会导致与预期相反的结果,所以不推荐使用。

3:如果脚本依赖于特定的后端,可以使用 use() 函数:

import matplotlib matplotlib.use('PS')   # generate postscript output by default 

如果使用 use() 函数,则必须在导入 matplotlib.pyplot 之前完成。在引入 pyplot 之后调用 use() 将不起作用。如果用户希望使用不同的后端,那么使用 use() 将需要对代码进行更改。所以除非绝对必要,因此应该避免显示调用 use()。

注意:
后端名称规范不区分大小写; 例如,”GTK3Agg”和”gtk3agg”是等效的。

作者:

喜欢围棋和编程。

 
发布于 分类 编程标签

发表评论

电子邮件地址不会被公开。