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
你可以点击相应图片的获得每一步的源码。
使用默认
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()
示例默认
在以下脚本中,我们示例(并注释)所有影响图像外观的图像设定。这些设定被显式地设置成它们的默认值,但是现在你可以交互地尝试这些值来探索它们的作用(参考之后的线条属性和线条样式)。
# 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()
更改色彩和线宽
首先,我们想要余弦是蓝色而正弦是红色,它们的线条都稍厚一点。我们将也稍微更改图片大小来使它更宽一点。
figure(figsize=(10,6), dpi=80)
plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plot(X, S, color="red", linewidth=2.5, linestyle="-")
设置边界
当前的图像边界有点太紧了一点,而且我们想要预留一点空间使数据点更清晰。
xlim(X.min()*1.1, X.max()*1.1)
ylim(C.min()*1.1, C.max()*1.1)
设置刻度
当前刻度并不理想,因为它们不显示正余弦中我们感兴趣的值(+/-π,+/-π/2)。我们将更改它们让它们只显式这些值。
xticks( [-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
yticks([-1, 0, +1])
设置刻度标签
刻度已经放置合适但是他们的标签并不很清楚,我们可以猜出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)
轴线(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))
添加图例
让我们在图片左上角添加一个图例。这仅仅需要向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')
注解某些点
让我们现在使用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{2pi}{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{2pi}{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"))
魔鬼在于细节
由于蓝色和红色的线,刻度标签现在很难看清。。我们可以让它们更大并且调整它们的属性使它们的背景半透明。这将让我们把数据和标签都看清。
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
或set_somethin
方法来设置图像属性。
子区(subplots)
你可以通过subplot在正常网格中布置图像。你需要指定行数和列数和区域的编号。注意gridspec命令是个更强大的选择。
子图(axes)
子图和子区(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中提供了特殊的定位器。
其它种类绘图
常规绘图
从下面的代码开始,尝试重新生成上边的填充图形。
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)
从以下代码开始,尝试生成上边的图形,注意标记大小,颜色和透明度。
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)
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
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)
从以下代码开始,尝试生成上边的图形,注意色彩表。(参见色彩表)
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
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
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)
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import *
n = 20
Z = np.random.uniform(0,1,n)
pie(Z), show()
提示:你需要改变Z。
点击图像获取答案。
矢量图(quiver plots)
从以下代码开始,尝试生成上边的图形,注意色彩和方向。
from pylab import *
n = 8
X,Y = np.mgrid[0:n,0:n]
quiver(X,Y), show()
提示:你需要画两次箭头。
点击图像获取答案。
网格(grids)
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import *
axes = gca()
axes.set_xlim(0,4)
axes.set_ylim(0,3)
axes.set_xticklabels([])
axes.set_yticklabels([])
show()
点击图像获取答案。
多图绘制
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
from pylab import *
subplot(2,2,1)
subplot(2,2,3)
subplot(2,2,4)
show()
提示:你可以对不同部分使用几个subplot命令。
点击图像获取答案。
极轴图
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
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这行。
点击图像获取答案。
三维绘图
从以下代码开始,尝试生成上边的图形,添加标签和红色条形。
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命令。
点击图像获取答案。
绘制文本
试着从头做这个!提示:看一看matplotlib logo
点击图像获取答案。
此教程之外
matplotlib受益于丰富的文档和巨大的用户和开发者社区。这有几个有关的链接:
教程
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也相当有用。每个例子和它的源码一同被提供。
一个较小的画廊在这里
邮件列表
最后,这里有一个用户邮件列表,那里你可以寻求帮助。一个开发者邮件列表是更加技术性的。
快速参考
没什么好翻译的,看原文吧……传送门