Matplotlib Tutorial(译)
Matplotlib Tutorial(译)
翻译自:Matplotlib tutorialNicolas P. Rougier - Euroscipy 2012
- toc {: toc}
这个教程基于可以从scipy lecture note得到的 Mike Müller的教程。
源代码可从这里获得。图像在figures文件夹内,所有的脚本位于scripts文件夹。
所有的代码和材料以Creative Commons Attribution 3.0 United States License (CC-by)发布。
特别感谢 Bill Wing 和 Christoph Deil 的检查和校正。
引言
matplotlib 大概是被使用最多的二维绘图 Python 包。它不仅提供一个非常快捷的用 python 可视化数据的方法,而且提供了出版质量的多种格式图像。我们将要探索 matplotlib 包含最常见情况的交互模式。
Ipython 和 pylab 模式
IPython是一个增强的 Python 交互 shell,它拥有很多有趣的特性包括被命名的输入与输出,可使用 shell 命令,增强的调试和许多其它特性。当我们在命令参数中用=-pylab=(自从 IPython0.12 版变成=–pylab=),它容许交互的 matplotlib 会话有像 Matlab/Mathematica 样的功能。
pylab
pylab 提供了一个针对 matplotlib 面向对象绘图库的程序界面。它模仿 Matlab(TM)开发。因此,pylab 大部分的绘图命令和参数和 Matlab(TM)相似。重要的命令被交互示例解释。
简单绘图
在这一部分,我们想在同一个图片中绘制正弦和余弦函数。从默认设置开始,我们将一步一步地改进使它看上去更棒。
首先获得正弦和余弦函数的数据:
from pylab import * X = np.linspace(-np.pi, np.pi, 256,endpoint=True) C,S = np.cos(X), np.sin(X)
X 现在是一个 numpy 数组,包含从-π到+π(包含π)等差分布的 256 个值。C是正弦(256 个值),S是余弦(256 个值)。
运行这个例子,你可以在 IPython 交互会话键入它们
[lyy@arch ~]$ ipython2 --pylab Python 2.7.3 (default, Apr 24 2012, 00:00:54) Type "copyright", "credits" or "license" for more information. IPython 0.13 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. Welcome to pylab, a matplotlib-based Python environment [backend: Qt4Agg]. For more information, type 'help(pylab)'.
或者你可以下载每个示例然后使用普通的的 python 运行它:
$ python exercice_1.py
你可以点击相应图片的获得每一步的源码。
使用默认
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice1.png]]
matplotlib 有一套允许定制各种属性的默认设置。你可以几乎控制 matplotlib 中的每一个默认属性:图像大小,每英寸点数,线宽,色彩和样式,子图(axes),坐标轴和网格属性,文字和字体属性,等等。虽然 matplotlib 的默认设置在大多数情况下相当好,你却可能想要在一些特别的情形下更改一些属性。
from pylab import * X = np.linspace(-np.pi, np.pi, 256,endpoint=True) C,S = np.cos(X), np.sin(X) plot(X,C) plot(X,S) show()
示例默认
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice2.png]]
在以下脚本中,我们示例(并注释)所有影响图像外观的图像设定。这些设定被显式地设置成它们的默认值,但是现在你可以交互地尝试这些值来探索它们的作用(参考之后的线条属性和线条样式)。
# Import everything from matplotlib (numpy is accessible via 'np' alias) from pylab import * # Create a new figure of size 8x6 points, using 80 dots per inch figure(figsize=(8,6), dpi=80) # Create a new subplot from a grid of 1x1 subplot(1,1,1) X = np.linspace(-np.pi, np.pi, 256,endpoint=True) C,S = np.cos(X), np.sin(X) # Plot cosine using blue color with a continuous line of width 1 (pixels) plot(X, C, color="blue", linewidth=1.0, linestyle="-") # Plot sine using green color with a continuous line of width 1 (pixels) plot(X, S, color="green", linewidth=1.0, linestyle="-") # Set x limits xlim(-4.0,4.0) # Set x ticks xticks(np.linspace(-4,4,9,endpoint=True)) # Set y limits ylim(-1.0,1.0) # Set y ticks yticks(np.linspace(-1,1,5,endpoint=True)) # Save figure using 72 dots per inch # savefig("exercice_2.png",dpi=72) # Show result on screen show()
更改色彩和线宽
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice3.png]]
首先,我们想要余弦是蓝色而正弦是红色,它们的线条都稍厚一点。我们将也稍微更改图片大小来使它更宽一点。
figure(figsize=(10,6), dpi=80) plot(X, C, color="blue", linewidth=2.5, linestyle="-") plot(X, S, color="red", linewidth=2.5, linestyle="-")
设置边界
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice4.png]]
当前的图像边界有点太紧了一点,而且我们想要预留一点空间使数据点更清晰。
xlim(X.min()*1.1, X.max()*1.1) ylim(C.min()*1.1, C.max()*1.1)
设置刻度
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice5.png]]
当前刻度并不理想,因为它们不显示正余弦中我们感兴趣的值(+/-π,+/-π/2)。我们将更改它们让它们只显式这些值。
xticks( [-np.pi, -np.pi/2, 0, np.pi/2, np.pi]) yticks([-1, 0, +1])
设置刻度标签
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice6.png]]
刻度已经放置合适但是他们的标签并不很清楚,我们可以猜出 3.142 是π但是最好让它更直接。当我们设置刻度值时,我们也可以在第二个参数列表中提供相应的标签。注意,我们用 latex 获得更好渲染的标签。
xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$']) yticks([-1, 0, +1], [r'$-1$', r'$0$', r'$+1$'])
移动轴线(spine)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice7.png]]
轴线(spines)是连接刻度标志和标示数据区域边界的线。它们现在可以被放置在任意地方,它们在子图的边缘。我们将改变这点,因为我们想让它们位于中间。因为一共有四个轴线(上/下/左/右)。我们将通过将它们的颜色设置成 None,舍弃位于顶部和右部轴线。然后我们把底部和左部的轴线移动到数据空间坐标中的零点。
ax = gca() ax.spines['right'].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))
添加图例
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice8.png]]
让我们在图片左上角添加一个图例。这仅仅需要向 plot 命令添加关键字参数 label(之后将被图例框使用)。
plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine") plot(X, S, color="red", linewidth=2.5, linestyle="-", label="sine") legend(loc='upper left')
注解某些点
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice9.png]]
让我们现在使用 annotate 命令注解一些我们感兴趣的点。我们选择 2π/3 作为我们想要注解的正弦和余弦值。我们将在曲线上做一个标记和一个垂直的虚线。然后,使用 annotate 命令来显示一个箭头和一些文本。
t = 2*np.pi/3 plot([t,t],[0,np.cos(t)], color ='blue', linewidth=2.5, linestyle="--") scatter([t,],[np.cos(t),], 50, color ='blue') annotate(r'$sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$', xy=(t, np.sin(t)), xycoords='data', xytext=(+10, +30), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2")) plot([t,t],[0,np.sin(t)], color ='red', linewidth=2.5, linestyle="--") scatter([t,],[np.sin(t),], 50, color ='red') annotate(r'$cos(\frac{2\pi}{3})=-\frac{1}{2}$', xy=(t, np.cos(t)), xycoords='data', xytext=(-90, -50), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
魔鬼在于细节
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/exercice10.png]]
由于蓝色和红色的线,刻度标签现在很难看清。。我们可以让它们更大并且调整它们的属性使它们的背景半透明。这将让我们把数据和标签都看清。
for label in ax.get_xticklabels() + ax.get_yticklabels(): label.set_fontsize(16) label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65 ))
图像,子区,子图,刻度(Figures,Subplots,Axes,Ticks)
Note:这一段很绕,我不知道该怎么翻译好。在 matplotlib 中 axes 容器处于核心地位。翻译成子图因为在《Python 科学计算》中作者这样称呼.subplot 翻译成子区
目前我们已经隐式地使用了图像(figure)和子图(axes)的创建。这对快速绘图很方便。我们通过显式使用 figure,subplot,axes 可以控制更多图像的呈现。一个图像(figure)意味着用户界面的整个窗口。在一个图像中可以有些子区(subplot)。subplot 将绘图放置在常规的网格位置上而 axes 允许更自由的放置。它们都非常有用,取决于你的意图。我们已经隐式地使用了 figure 和 subplot。当我们调用 plot 时,matplotlib 调用 gca 来获取当前 axes 反过来调用 gcf()获取当前图像(figure)。如果没有当前图像(figure),它调用 figure()创建一个,严格地说,是创建一个 subplot(111)。让我们详细看看。
图像(Figure)
图像是一个图形用户界面的窗口,以"Figure #"作为标题。相对于 Python 通常是 0 索引的,图像是从一开始的。这显然是 matlab 风格。这里有几个决定图像外观的参数:
参数 | 默认 | 描述 |
---|---|---|
num | 1 | 图像编号 |
figsize | figure.figsize | 图像大小(宽度,高度)(英寸) |
dpi | figure.dpi | 每英寸分辨率 |
facecolor | figure.facecolor | 背景色 |
edgecolor | figure.edgecolor | 绘图背景边沿色 |
frameon | True | 绘制框架与否 |
默认可以在资源文件1指定,并将在大多数时间被使用。只有图像的编号频繁变动。
当你使用图形用户界面时,你可以通过点击右上角2的=x=来关闭一个图像。但也可以用一种编程方式调用 close 来关闭一个图像。取决于参数它关闭(1)当前图像(无参数),(2)一个指定的图像(以图像编号或图像实例作为参数),(3)所有图像(以 all 作为参数)。
和其它对象一样,你可以通过=setp=或=setsomethin=方法来设置图像属性。
子区(subplots)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/subplot-horizontal.png]]
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/subplot-vertical.png]]
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/subplot-grid.png]]
你可以通过 subplot 在正常网格中布置图像。你需要指定行数和列数和区域的编号。注意gridspec命令是个更强大的选择。
子图(axes)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/gridspec.png]]
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/axes.png]]
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/axes-2.png]]
子图和子区(subplot)非常相似,但是允许把图片放置到图像(figure)中的任何地方。所以如果我们想要在一个大图片中嵌套一个小点的图片,我们通过子图(axes)来完成它。
刻度(ticks)
良好格式化的刻度是准备发表的图片中的重要部分。Matplotlib 为刻度提供完全可配置的系统。刻度定位器指定刻度出现的位置,刻度格式器让刻度看起来如你所愿。主刻度和次要刻度可以分别放置和格式化,每个默认主刻度并不显示,也就是,它们只有一个空列表,因为它们作为空定位器(NullLocator)(参见下面)。
-
刻度定位器(Tick Locator)
这有几个针对不同种类需求的各种定位器:
Class Description NullLocator 没有刻度. IndexLocator 每到一个基数的倍数点放置一个刻度 FixedLocator 刻度位置是固定的 LinearLocator 决定刻度位置 MultipleLocator 在每个基于基数倍数的整数点放置刻度 AutoLocator 在不错的位置选择不超过 n 个间隔 LogLocator 以 log 坐标决定刻度位置 所有这些定位器源于 matplotlib 基类 matplotlib.ticker.Locator。你可以源于它创建你自己的定位器。处理时间刻度可能非常棘手。因此,matplotlib 在 matplotlib.dates 中提供了特殊的定位器。
其它种类绘图
常规绘图
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/plotex.png]]
从下面的代码开始,尝试重新生成上边的填充图形。
from pylab import * n = 256 X = np.linspace(-np.pi,np.pi,n,endpoint=True) Y = np.sin(2*X) plot (X, Y+1, color='blue', alpha=1.00) plot (X, Y-1, color='blue', alpha=1.00) show()
提示:你需要使用fill\between命令。
点击图片获取答案。
散点图(scatter plots)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/scatterex.png]]
从以下代码开始,尝试生成上边的图形,注意标记大小,颜色和透明度。
from pylab import * n = 1024 X = np.random.normal(0,1,n) Y = np.random.normal(0,1,n) scatter(X,Y) show()
提示:色彩由(X,Y)角度给出。
点击图像获取答案。
条形图(bar plots)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/barex.png]]
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import * n = 12 X = np.arange(n) Y1 = (1-X/float(n)) * np.random.uniform(0.5,1.0,n) Y2 = (1-X/float(n)) * np.random.uniform(0.5,1.0,n) bar(X, +Y1, facecolor='#9999ff', edgecolor='white') bar(X, -Y2, facecolor='#ff9999', edgecolor='white') for x,y in zip(X,Y1): text(x+0.4, y+0.05, '%.2f' % y, ha='center', va= 'bottom') ylim(-1.25,+1.25) show()
提示:你要注意文本对齐。
点击图像获取答案。
等高线图(contour plots)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/contourex.png]]
从以下代码开始,尝试生成上边的图形,注意色彩表。(参见色彩表)
from pylab import * def f(x,y): return (1-x/2+x**5+y**3)*np.exp(-x**2-y**2) n = 256 x = np.linspace(-3,3,n) y = np.linspace(-3,3,n) X,Y = np.meshgrid(x,y) contourf(X, Y, f(X,Y), 8, alpha=.75, cmap='jet') C = contour(X, Y, f(X,Y), 8, colors='black', linewidth=.5) show()
提示:你需要使用clabel命令。
点击图像获取答案。
Imshow
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/imshowex.png]]
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import * def f(x,y): return (1-x/2+x**5+y**3)*np.exp(-x**2-y**2) n = 10 x = np.linspace(-3,3,4*n) y = np.linspace(-3,3,3*n) X,Y = np.meshgrid(x,y) imshow(f(X,Y)), show()
提示:你需要注意 imshow 命令中图像的\来源\_,并且使用色彩条(colorbar)。
点击图像获取答案。
饼图(Pie charts)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/pieex.png]]
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import * n = 20 Z = np.random.uniform(0,1,n) pie(Z), show()
提示:你需要改变 Z。
点击图像获取答案。
矢量图(quiver plots)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/quiverex.png]]
从以下代码开始,尝试生成上边的图形,注意色彩和方向。
from pylab import * n = 8 X,Y = np.mgrid[0:n,0:n] quiver(X,Y), show()
提示:你需要画两次箭头。
点击图像获取答案。
网格(grids)
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/gridex.png]]
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import * axes = gca() axes.set_xlim(0,4) axes.set_ylim(0,3) axes.set_xticklabels([]) axes.set_yticklabels([]) show()
点击图像获取答案。
多图绘制
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/multiplotex.png]]
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import * subplot(2,2,1) subplot(2,2,3) subplot(2,2,4) show()
提示:你可以对不同部分使用几个 subplot 命令。
点击图像获取答案。
极轴图
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/polarex.png]]
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import * axes([0,0,1,1]) N = 20 theta = np.arange(0.0, 2*np.pi, 2*np.pi/N) radii = 10*np.random.rand(N) width = np.pi/4*np.random.rand(N) bars = bar(theta, radii, width=width, bottom=0.0) for r,bar in zip(radii, bars): bar.set_facecolor( cm.jet(r/10.)) bar.set_alpha(0.5) show()
提示:你仅仅需要修改\axes\这行。
点击图像获取答案。
三维绘图
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/plot3dex.png]]
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import * from mpl_toolkits.mplot3d import Axes3D fig = figure() ax = Axes3D(fig) X = np.arange(-4, 4, 0.25) Y = np.arange(-4, 4, 0.25) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='hot') show()
提示:你需要使用contourf命令。
点击图像获取答案。
绘制文本
[[http://www.loria.fr/~rougier/teaching/matplotlib/figures/textex.png]]
试着从头做这个!提示:看一看matplotlib logo
点击图像获取答案。
此教程之外
matplotlib 受益于丰富的文档和巨大的用户和开发者社区。这有几个有关的链接:
教程
pyplot教程
图像教程
文本教程
artist对象教程
路径教程
变换教程
matplotlib 文档
用户手册
常见问题
截图
代码文档
代码相当好的文档化了,你可以在 python 会话中快速查询指定命令
>>> from pylab import * >>> help(plot) Help on function plot in module matplotlib.pyplot: plot(*args, **kwargs) Plot lines and/or markers to the :class:`~matplotlib.axes.Axes`. *args* is a variable length argument, allowing for multiple *x*, *y* pairs with an optional format string. For example, each of the following is legal:: plot(x, y) # plot x and y using default line style and color plot(x, y, 'bo') # plot x and y using blue circle markers plot(y) # plot y using x as index array 0..N-1 plot(y, 'r+') # ditto, but with red plusses If *x* and/or *y* is 2-dimensional, then the corresponding columns will be plotted.
画廊(Galleries)
当你搜寻如何绘制指定图像时,matplotlib gallery也相当有用。每个例子和它的源码一同被提供。
一个较小的画廊在这里
邮件列表
最后,这里有一个用户邮件列表,那里你可以寻求帮助。一个开发者邮件列表是更加技术性的。
快速参考
没什么好翻译的,看原文吧……传送门