作者: Nicolas Rougier, Mike Müller, Gaël Varoquaux

原文: http://www.scipy-lectures.org/intro/matplotlib/index.html

1.4.1 简介

Matplotlib 可能是Python唯一一个最广泛使用的二维图包。它同时提供了从Python中可视化数据非常的快速方式以及多种格式的出版质量图片。我们将在交互模式下研究Matplotlib,包含大多数的常用案例。

1.4.1.1 IPython和matplotlib模式

IPython是强化版交互Python shell,有许多有趣的功能,包括:输入输出的命名、访问shell命令改进错误排除等。它位于Python中的科学计算工作流的核心,要让它与Matplotlib的结合使用:

用命令行参数 --matplotlib 启动IPython,获得带有Matlab/Mathematica类似功能的交互Matplotlib session。

在 Jupyter Notebook 中,在notebook的最前端,使用如下的魔法指令: %matplotlib inline

1.4.1.2 pyplot

pyplot提供了matplotlib面向对象的绘图库的程序接口。它的模型与Matlab™非常相近。因此,pylab中的绝大多数绘图命令Matlab™都有带有相似函数的类似实现。重要的命令会以交互例子来解释。

In [1]:
%matplotlib inline
from matplotlib import pyplot as plt

1.4.2 简单绘图

在这个部分,我们将在同一个图像中绘制cosine和sine函数。从默认设置开始,我们将不断丰富图片,让它看起来更漂亮。

第一步获得sine和cosine函数的数据:

In [2]:
import numpy as np

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)

X现在是Numpy数组,范围是之间(包含)的256个值。C是cosine(256个值),而S是sine(256个值)

要运行例子,你可以在IPython的交互session中输入这些命令:

ipython --pylab

这会将我们带到IPython提示符:

IPython 2.3.1 -- 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.
Using matplotlib backend: MacOSX

你可以下载每个示例,然后用平常的Python运行,但是,你将没法动态的数据操作:

python exercice_1.py

通过点击对应的图片,你可以获得每一步的源码。

[译者注] 我们将在 Jupyter Notebook 来交互式演示每一个例子

1.4.2.1 用默认设置绘图


提示:文档


Matplotlib有一组默认设置,允许自定义所有的属性。你几乎可以控制在matplotlib中的所有属性:图片大小和dpi、线长度、颜色和样式、坐标轴、坐标轴和网格属性、文本和字体属性等等。

In [3]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_1.html

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)

plt.plot(X, C)
plt.plot(X, S)

plt.show()

1.4.2.2 默认值示例


提示:文档


在下面的脚本中,我们标示(备注)了影响绘图外观的所有图片设置。

这些设置被显式的设置为默认值,但是现在你可以交互的实验这些值以便验证他们的效果(看一下下面的线属性线样式)。

In [4]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_2.html

# Create a figure of size 8x6 inches, 80 dots per inch
plt.figure(figsize=(8, 6), dpi=80)

# Create a new subplot from a grid of 1x1
plt.subplot(1, 1, 1)

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)

# Plot cosine with a blue continuous line of width 1 (pixels)
plt.plot(X, C, color="blue", linewidth=1.0, linestyle="-")

# Plot sine with a green continuous line of width 1 (pixels)
plt.plot(X, S, color="green", linewidth=1.0, linestyle="-")

# Set x limits
plt.xlim(-4.0, 4.0)

# Set x ticks
plt.xticks(np.linspace(-4, 4, 9, endpoint=True))

# Set y limits
plt.ylim(-1.0, 1.0)

# Set y ticks
plt.yticks(np.linspace(-1, 1, 5, endpoint=True))

# Save figure using 72 dots per inch
# plt.savefig("exercice_2.png", dpi=72)

# Show result on screen
plt.show()

1.4.2.3 改变颜色和线宽度


提示:文档


首先,我们想要cosine是蓝色,sine是红色,两者都是稍稍粗一点的线。我们也改变了一点图片的大小,让它更加水平。

plt.figure(figsize=(10, 6), dpi=80)
plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red",  linewidth=2.5, linestyle="-")
In [5]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_3.html

plt.figure(figsize=(8, 5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")

plt.xlim(-4.0, 4.0)
plt.xticks(np.linspace(-4, 4, 9, endpoint=True))

plt.ylim(-1.0, 1.0)
plt.yticks(np.linspace(-1, 1, 5, endpoint=True))

plt.show()

1.4.2.4 设置极值


提示:文档


当前的图片的极值限制太拥挤了,我们希望留一点空间以便清晰的看到所有的数据点。

plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.ylim(C.min() * 1.1, C.max() * 1.1)
In [6]:
import numpy as np
import matplotlib.pyplot as plt


# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_4.html

plt.figure(figsize=(8, 5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
S = np.sin(X)
C = np.cos(X)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")

plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.ylim(C.min() * 1.1, C.max() * 1.1)

plt.show()

1.4.2.5 设置坐标轴刻度值

提示:文档

现在的刻度不太理想,因为他们没有显示对于sine和cosine有意义的值(+/-π,+/-π/2)。我们将改变这些刻度,让他们只显示这些值。

plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, +1])
In [7]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_5.html

plt.figure(figsize=(8, 5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
S = np.sin(X)
C = np.cos(X)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")

plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])

plt.ylim(C.min() * 1.1, C.max() * 1.1)
plt.yticks([-1, 0, +1])

plt.show()

1.4.2.6 设置刻度标签

提示:文档

刻度现在放在了正确的位置,但是标签并不是显而易见。我们能想到3.14是π,但是最好让它更明确。

当我们设置了刻度值,我们也可以在第二个参数中列出对应的标签。注意我们用latex以便更好的渲染标签。

plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])

plt.yticks([-1, 0, +1],
          [r'$-1$', r'$0$', r'$+1$'])
In [8]:
import numpy as np
import matplotlib.pyplot as plt

plt.figure(figsize=(8, 5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C = np.cos(X)
S = np.sin(X)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")

plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])

plt.ylim(C.min() * 1.1, C.max() * 1.1)
plt.yticks([-1, 0, +1],
          [r'$-1$', r'$0$', r'$+1$'])

plt.show()

1.4.2.7 移动脊柱

提示:文档

脊柱是连接坐标轴刻度标记的线,记录了数据范围的边界。他们可以被放在任意的位置,到目前位置,他们被放在了坐标轴的四周。我们将改变他们,因为我们希望他们在中间。因为有四条(上下左右),我们通过设置颜色为None舍弃了顶部和右侧,并且我们将把底部和左侧的脊柱移动到数据空间坐标的零点。

ax = plt.gca()  # gca stands for 'get current axis'
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))
In [9]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_7.html
    
plt.figure(figsize=(8,5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256,endpoint=True)
C = np.cos(X)
S = np.sin(X)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")

ax = plt.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))

plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])

plt.ylim(C.min() * 1.1, C.max() * 1.1)
plt.yticks([-1, 0, +1],
          [r'$-1$', r'$0$', r'$+1$'])

plt.show()

1.4.2.8 添加图例

提示:文档

让我们在坐上角添加图例。这只需要在plot命里中添加关键词参数label(将被用于图例框)。

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red",  linewidth=2.5, linestyle="-", label="sine")

plt.legend(loc='upper left')
In [10]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_8.html

plt.figure(figsize=(8,5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256,endpoint=True)
C = np.cos(X)
S = np.sin(X)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-",  label="sine")

ax = plt.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))

plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])

plt.ylim(C.min() * 1.1, C.max() * 1.1)
plt.yticks([-1, +1],
          [r'$-1$', r'$+1$'])

plt.legend(loc='upper left')

plt.show()

1.4.2.9 标注一些点

提示:文档

让我们用annotate命令标注一些有趣的点。我们选取值2π/3,我们想要标注sine和cosine。首先我们在曲线上画出了一个垂直的散点标记线。然后,我们将用annotate命令显示带有箭头的文字。

t = 2 * np.pi / 3
plt.plot([t, t], [0, np.cos(t)], color='blue', linewidth=2.5, linestyle="--")
plt.scatter([t, ], [np.cos(t), ], 50, color='blue')

plt.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"))

plt.plot([t, t],[0, np.sin(t)], color='red', linewidth=2.5, linestyle="--")
plt.scatter([t, ],[np.sin(t), ], 50, color='red')

plt.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"))
In [11]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/matplotlib/auto_examples/plot_exercice_9.html

plt.figure(figsize=(8, 5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256,endpoint=True)
C = np.cos(X)
S = np.sin(X)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-",  label="sine")

ax = plt.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))

plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])

plt.ylim(C.min() * 1.1, C.max() * 1.1)
plt.yticks([-1, +1],
          [r'$-1$', r'$+1$'])

t = 2*np.pi/3
plt.plot([t, t], [0, np.cos(t)],
        color='blue', linewidth=1.5, linestyle="--")
plt.scatter([t, ], [np.cos(t), ], 50, color='blue')
plt.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"))

plt.plot([t, t], [0, np.sin(t)],
        color='red', linewidth=1.5, linestyle="--")
plt.scatter([t, ], [np.sin(t), ], 50, color='red')
plt.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"))

plt.legend(loc='upper left')

plt.show()

1.4.2.10 细节是魔鬼

提示:文档

因为蓝色和红色的线,刻度标签很难看到。我们可以让他们更大一些,也可以调整他们的属性以便他们被处理为半透明的白色背景。这样我们就可以同时看到数据和标签。

for label in ax.get_xticklabels() + ax.get_yticklabels():
    label.set_fontsize(16)
    label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))
In [12]:
import numpy as np
import matplotlib.pyplot as plt

# http://scipy-lectures.github.io/intro/auto_examples/plot_exercice_10.html

plt.figure(figsize=(8, 5), dpi=80)
plt.subplot(111)

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)

ax = plt.gca()

# set right and top color to none
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

# move bottom and left to coordinate 0
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))

# set tick to a semi-transparent white background
for label in ax.get_xticklabels() + ax.get_yticklabels():
    label.set_fontsize(16)
    label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65 ))
    

# set x and y ticks value and the labels on the position
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
       [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
plt.yticks([-1, 0, +1],
       [r'$-1$', r'$0$', r'$+1$'])

# set x and y limits
plt.xlim(X.min()*1.1, X.max()*1.1)
plt.ylim(C.min()*1.1, C.max()*1.1)

plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red",  linewidth=2.5, linestyle="-", label="sine")

# set legend
plt.legend(loc='upper left', frameon=True, fancybox=True)

# annotate
t = 2*np.pi/3
plt.plot([t,t],[0,np.cos(t)], color ='blue', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.cos(t),], 50, color ='blue')

plt.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"))

plt.plot([t,t],[0,np.sin(t)], color ='red', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.sin(t),], 50, color ='red')

plt.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"))

plt.show()

1.4.3 图形、子图、轴和刻度

在matplotlib中“图形”是用户界面中的整个窗口。在这个图形中可以有“子图”。

到目前为止,我们已经使用图形和创建数轴。这对于快速绘图是非常方便的。使用图形、子图和轴我们可以控制显示。尽管子图将图表放在标准的网格中,轴可以在图形中放在任意位置。根据你的目的不同,二者都非常有用。我们也在没有显式的调用图形和子图时使用了他们。当我们调用plot时,matplotlib调用gca()来获得当前的坐标轴,相应的调用gcf()获得当前的图形。如果没有当前图形,那么将调用figure()去创建一个,严格来说是创建一个`subplot(111)。让我们来详细看一下。

1.4.3.1 图形

图形是在GUI中的窗口,标题是"Figure #"。图形的标号从1开始,而不是常规的Python方式从0开始。这明显是MATLAB-风格。这些参数决定图形的外观:

参数 默认值 描述
num 1 图形编号
figsize figure.figsize 以英寸表示的图形大小(宽、高)
dpi figure.dpi 分辨率以每英寸点数表示
facecolor figure.facecolor 背景色
edgecolor figure.edgecolor 背景边缘色
frameon True 是否绘制框架

默认值可以在资源文件中指明,并在绝大数时间使用。只有图形数经常被改变。

与其他对象类似,你可以用setp或者set_something方法设置图形属性。

当你使用GUI工作时,你可以点击右上的X关闭图形。但是,你可以通过调用close用程序关闭图形。根据参数关闭不同内容(1)当前图形(没有参数),(2)特定图形(用图形编号或图形实例做参数),(3)所有图形("all"作为参数)。

pl.close(1)     # Closes figure 1

1.4.3.2 子图

用子图你可以将图片放置在标准方格中。你需要指定行列数和图片数。 注意gridspec命令相对更加高级。

plot_subplot-horizontal_1.pngplot_subplot-vertical_1.pngplot_subplot-grid_1.pngplot_gridspec_1.png

1.4.3.3 轴

轴与子图非常类似,不过允许图形放在图片的任意位置。因此,如果我们想要将一个小图形放在一个更大图形中,我们可以用轴。

plot_axes_1.pngplot_axes-2_1.png

1.4.3.4 刻度

格式良好的刻度是准备好发布图片的必要部分。Matplotlib提供了一个完全可控的刻度系统。有刻度位置来指定刻度该出现在哪,还有刻度格式来给出你想要的刻度外观。主刻度和子刻度可以被独立放置和整理格式。之前子刻度默认是不显示的,即他们只有空列表,因为它是NullLocator (见下面)。

1.4.3.4.1 刻度位置

刻度位置可以控制的位置。它的设置如下:

ax = pl.gca()
ax.xaxis.set_major_locator(eval(locator))

不同的需求有多种位置:

plot_ticks_1.png

所有这些位置都可以从基础类matplotlib.ticker.Locator衍生出来。你可以从中衍生出你自己的位置。将日期处理为刻度特别困哪。因此,matplotlib提供了特殊的位置matplotlib.dates

1.4.4 其他类型的图形:例子与练习

1.4.4.1 常规图形


提示:你可以使用fill_between命令。


plot_plot_ex_1.png

从下面的代码开始,试着重新生成这个图片,小心处理填充区域:

n = 256
X = np.linspace(-np.pi, np.pi, n, endpoint=True)
Y = np.sin(2 * X)

plt.plot(X, Y + 1, color='blue', alpha=1.00)
plt.plot(X, Y - 1, color='blue', alpha=1.00)

答案如下:

In [13]:
import numpy as np
import matplotlib.pyplot as plt

# http://www.scipy-lectures.org/intro/matplotlib/auto_examples/plot_plot.html

n = 256
X = np.linspace(-np.pi, np.pi, n, endpoint=True)
Y = np.sin(2 * X)

plt.axes([0.025, 0.025, 0.95, 0.95])

plt.plot(X, Y + 1, color='blue', alpha=1.00)
plt.fill_between(X, 1, Y + 1, color='blue', alpha=.25)

plt.plot(X, Y - 1, color='blue', alpha=1.00)
plt.fill_between(X, -1, Y - 1, (Y - 1) > -1, color='blue', alpha=.25)
plt.fill_between(X, -1, Y - 1, (Y - 1) < -1, color='red',  alpha=.25)

plt.xlim(-np.pi, np.pi)
plt.xticks(())
plt.ylim(-2.5, 2.5)
plt.yticks(())

plt.show()

1.4.4.2 散点图


提示:颜色根据角度进行分配


plot_scatter_ex_1.png

从下面的代码开始,试着重新生成这个图片,小心处理标记的大小颜色和透明度:

n = 1024
X = np.random.normal(0,1,n)
Y = np.random.normal(0,1,n)

plt.scatter(X,Y)

答案如下:

In [14]:
import numpy as np
import matplotlib.pyplot as plt

# http://www.scipy-lectures.org/intro/matplotlib/auto_examples/plot_scatter.html

n = 1024
X = np.random.normal(0, 1, n)
Y = np.random.normal(0, 1, n)
T = np.arctan2(Y, X)

plt.axes([0.025, 0.025, 0.95, 0.95])
plt.scatter(X, Y, s=75, c=T, alpha=.5)

plt.xlim(-1.5, 1.5)
plt.xticks(())
plt.ylim(-1.5, 1.5)
plt.yticks(())

plt.show()

1.4.4.3 柱状图


提示:你需要小心文本对齐


plot_bar_ex_1.png

从下面的代码开始,试着重新生成这个图片,添加红柱的标签。

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)

plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')

for x, y in zip(X, Y1):
    plt.text(x + 0.4, y + 0.05, '%.2f' % y, ha='center', va='bottom')

plt.ylim(-1.25, +1.25)

答案如下:

In [15]:
import numpy as np
import matplotlib.pyplot as plt

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)

plt.axes([0.025, 0.025, 0.95, 0.95])
plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')

for x, y in zip(X, Y1):
    plt.text(x + 0.4, y + 0.05, '%.2f' % y, ha='center', va= 'bottom')

for x, y in zip(X, Y2):
    plt.text(x + 0.4, -y - 0.05, '%.2f' % y, ha='center', va= 'top')

plt.xlim(-.5, n)
plt.xticks(())
plt.ylim(-1.25, 1.25)
plt.yticks(())

plt.show()

1.4.4.4 轮廓图


提示:你需要是使用clabel命令。


plot_contour_ex_1.png

从下面的代码开始,试着重新生成这个图片,小心处理colormap (见下面的Colormaps)。

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)

plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap='jet')
C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)

答案如下:

In [16]:
import numpy as np
import matplotlib.pyplot as plt

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)

plt.axes([0.025, 0.025, 0.95, 0.95])

plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap=plt.cm.hot)
C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)
plt.clabel(C, inline=1, fontsize=10)

plt.xticks(())
plt.yticks(())
plt.show()

1.4.4.5 Imshow


提示:你需要小心处理在imshow命令中的图像原点并使用colorbar


plot_imshow_ex_1.png

从下面的代码开始,试着重新生成这个图片,小心处理colormap和图像插入以及原点。

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)
plt.imshow(f(X, Y))

答案如下:

In [17]:
import numpy as np
import matplotlib.pyplot as plt

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, 3.5 * n)
y = np.linspace(-3, 3, 3.0 * n)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)

plt.axes([0.025, 0.025, 0.95, 0.95])
plt.imshow(Z, interpolation='nearest', cmap='bone', origin='lower')
plt.colorbar(shrink=.92)

plt.xticks(())
plt.yticks(())
plt.show()
/Users/linyong/anaconda/envs/pydata/lib/python3.6/site-packages/ipykernel_launcher.py:8: DeprecationWarning: object of type <class 'float'> cannot be safely interpreted as an integer.
  
/Users/linyong/anaconda/envs/pydata/lib/python3.6/site-packages/ipykernel_launcher.py:9: DeprecationWarning: object of type <class 'float'> cannot be safely interpreted as an integer.
  if __name__ == '__main__':

1.4.4.6 饼图


提示:你需要调整Z。


plot_pie_ex_1.png

从下面的代码开始,试着重新生成这个图片,小心处理颜色和切片大小。

Z = np.random.uniform(0, 1, 20)
plt.pie(Z)

答案如下:

In [18]:
import numpy as np
import matplotlib.pyplot as plt

n = 20
Z = np.ones(n)
Z[-1] *= 2

plt.axes([0.025, 0.025, 0.95, 0.95])

plt.pie(Z, explode=Z*.05, colors = ['%f' % (i/float(n)) for i in range(n)])
plt.axis('equal')
plt.xticks(())
plt.yticks()

plt.show()

1.4.4.7 梯度图


提示:你需要绘制两次箭头。


plot_quiver_ex_1.png

从下面的代码开始,试着重新生成这个图片,小心处理颜色和方向。

n = 8
X, Y = np.mgrid[0:n, 0:n]
plt.quiver(X, Y)

答案如下:

In [19]:
import numpy as np
import matplotlib.pyplot as plt

n = 8
X, Y = np.mgrid[0:n, 0:n]
T = np.arctan2(Y - n / 2., X - n/2.)
R = 10 + np.sqrt((Y - n / 2.0) ** 2 + (X - n / 2.0) ** 2)
U, V = R * np.cos(T), R * np.sin(T)

plt.axes([0.025, 0.025, 0.95, 0.95])
plt.quiver(X, Y, U, V, R, alpha=.5)
plt.quiver(X, Y, U, V, edgecolor='k', facecolor='None', linewidth=.5)

plt.xlim(-1, n)
plt.xticks(())
plt.ylim(-1, n)
plt.yticks(())

plt.show()

1.4.4.8 网格

plot_grid_ex_1.png

从下面的代码开始,试着重新生成这个图片,小心处理线的样式。

axes = plt.gca()
axes.set_xlim(0, 4)
axes.set_ylim(0, 3)
axes.set_xticklabels([])
axes.set_yticklabels([])

答案如下:

In [20]:
import matplotlib.pyplot as plt

ax = plt.axes([0.025, 0.025, 0.95, 0.95])

ax.set_xlim(0,4)
ax.set_ylim(0,3)
ax.xaxis.set_major_locator(plt.MultipleLocator(1.0))
ax.xaxis.set_minor_locator(plt.MultipleLocator(0.1))
ax.yaxis.set_major_locator(plt.MultipleLocator(1.0))
ax.yaxis.set_minor_locator(plt.MultipleLocator(0.1))
ax.grid(which='major', axis='x', linewidth=0.75, linestyle='-', color='0.75')
ax.grid(which='minor', axis='x', linewidth=0.25, linestyle='-', color='0.75')
ax.grid(which='major', axis='y', linewidth=0.75, linestyle='-', color='0.75')
ax.grid(which='minor', axis='y', linewidth=0.25, linestyle='-', color='0.75')
ax.set_xticklabels([])
ax.set_yticklabels([])

plt.show()

1.4.4.9 多图


提示:你可以用不同的分割来使用多个子图。


plot_multiplot_ex_1.png

pl.subplot(2, 2, 1)
pl.subplot(2, 2, 3)
pl.subplot(2, 2, 4)

答案如下:

In [21]:
import matplotlib.pyplot as plt

fig = plt.figure()
fig.subplots_adjust(bottom=0.025, left=0.025, top = 0.975, right=0.975)

plt.subplot(2, 1, 1)
plt.xticks(()), plt.yticks(())

plt.subplot(2, 3, 4)
plt.xticks(())
plt.yticks(())

plt.subplot(2, 3, 5)
plt.xticks(())
plt.yticks(())

plt.subplot(2, 3, 6)
plt.xticks(())
plt.yticks(())

plt.show()

1.4.4.10 极坐标系


提示:你只需要修改axes行。


plot_polar_ex_1.png

从下面的代码开始,试着重新生成这个图片。

plt.axes([0, 0, 1, 1])

N = 20
theta = np.arange(0., 2 * np.pi, 2 * np.pi / N)
radii = 10 * np.random.rand(N)
width = np.pi / 4 * np.random.rand(N)
bars = plt.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)

答案如下:

In [22]:
import numpy as np
import matplotlib.pyplot as plt

ax = plt.axes([0.025, 0.025, 0.95, 0.95], polar=True)

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 = plt.bar(theta, radii, width=width, bottom=0.0)

for r,bar in zip(radii, bars):
    bar.set_facecolor(plt.cm.jet(r/10.))
    bar.set_alpha(0.5)

ax.set_xticklabels([])
ax.set_yticklabels([])
plt.show()

1.4.4.11 3D绘图


提示:你需要使用contourf


plot_plot3d_ex_1.png

从下面的代码开始,试着重新生成这个图片。

from mpl_toolkits.mplot3d import Axes3D

fig = plt.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')

更多请见用Mayavi 3D绘图

答案如下:

In [23]:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.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=plt.cm.hot)
ax.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.cm.hot)
ax.set_zlim(-2, 2)

plt.show()

1.4.4.12 文本


提示:看一下matplotlib标识


plot_text_ex_1.png

试着从头开始做这个事情!

答案如下:

In [24]:
import numpy as np
import matplotlib.pyplot as plt


eqs = []
eqs.append((r"$W^{3\beta}_{\delta_1 \rho_1 \sigma_2} = U^{3\beta}_{\delta_1 \rho_1} + \frac{1}{8 \pi 2} \int^{\alpha_2}_{\alpha_2} d \alpha^\prime_2 \left[\frac{ U^{2\beta}_{\delta_1 \rho_1} - \alpha^\prime_2U^{1\beta}_{\rho_1 \sigma_2} }{U^{0\beta}_{\rho_1 \sigma_2}}\right]$"))
eqs.append((r"$\frac{d\rho}{d t} + \rho \vec{v}\cdot\nabla\vec{v} = -\nabla p + \mu\nabla^2 \vec{v} + \rho \vec{g}$"))
eqs.append((r"$\int_{-\infty}^\infty e^{-x^2}dx=\sqrt{\pi}$"))
eqs.append((r"$E = mc^2 = \sqrt{{m_0}^2c^4 + p^2c^2}$"))
eqs.append((r"$F_G = G\frac{m_1m_2}{r^2}$"))

plt.axes([0.025, 0.025, 0.95, 0.95])

for i in range(24):
    index = np.random.randint(0, len(eqs))
    eq = eqs[index]
    size = np.random.uniform(12, 32)
    x,y = np.random.uniform(0, 1, 2)
    alpha = np.random.uniform(0.25, .75)
    plt.text(x, y, eq, ha='center', va='center', color="#11557c", alpha=alpha,
         transform=plt.gca().transAxes, fontsize=size, clip_on=True)
plt.xticks(())
plt.yticks(())

plt.show()