3.1.md 13.0 KB
Newer Older
W
v2.0  
wizardforcel 已提交
1
# pyplot 教程
W
3.1  
wizardforcel 已提交
2 3 4 5 6 7 8

> 原文:[Pyplot tutorial](http://matplotlib.org/users/pyplot_tutorial.html)

> 译者:[飞龙](https://github.com/)

> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)

W
3.3  
wizardforcel 已提交
9
`matplotlib.pyplot`是一个命令风格函数的集合,使`matplotlib`的机制更像 MATLAB。 每个绘图函数对图像进行一些更改:例如,创建图像,在图像中创建绘图区域,在绘图区域绘制一些线条,使用标签装饰绘图等。在`matplotlib.pyplot`中,各种状态跨函数调用保存,以便跟踪诸如当前图像和绘图区域之类的东西,并且绘图函数始终指向当前轴域(请注意,这里和文档中的大多数位置中的『轴域』(axes)是指图像的一部分(两条坐标轴围成的区域),而不是指代多于一个轴的严格数学术语)。
W
3.1  
wizardforcel 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

```py
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.ylabel('some numbers')
plt.show()
```

![](http://matplotlib.org/_images/pyplot_simple.png)

你可能想知道为什么`x`轴的范围为`0-3``y`轴的范围为`1-4`。 如果你向`plot()`命令提供单个列表或数组,则`matplotlib`假定它是一个`y`值序列,并自动为你生成`x`值。 由于 python 范围从 0 开始,默认`x`向量具有与`y`相同的长度,但从 0 开始。因此`x`数据是`[0,1,2,3]`

`plot()`是一个通用命令,并且可接受任意数量的参数。 例如,要绘制`x``y`,你可以执行命令:

```py
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
```

对于每个`x,y`参数对,有一个可选的第三个参数,它是指示图像颜色和线条类型的格式字符串。 格式字符串的字母和符号来自 MATLAB,并且将颜色字符串与线型字符串连接在一起。 默认格式字符串为`"b-"`,它是一条蓝色实线。 例如,要绘制上面的红色圆圈,你需要执行:

```py
import matplotlib.pyplot as plt
plt.plot([1,2,3,4], [1,4,9,16], 'ro')
plt.axis([0, 6, 0, 20])
plt.show()
```

![](http://matplotlib.org/_images/pyplot_formatstr.png)

W
3.3  
wizardforcel 已提交
39
有关线型和格式字符串的完整列表,请参见[`plot()`文档](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot)。 上例中的`axis()`命令接收`[xmin,xmax,ymin,ymax]`的列表,并指定轴域的可视区域。
W
3.1  
wizardforcel 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

如果`matplotlib`仅限于使用列表,它对于数字处理是相当无用的。 一般来说,你可以使用`numpy`数组。 事实上,所有序列都在内部转换为`numpy`数组。 下面的示例展示了使用数组和不同格式字符串,在一条命令中绘制多个线条。

```py
import numpy as np
import matplotlib.pyplot as plt

# evenly sampled time at 200ms intervals
t = np.arange(0., 5., 0.2)

# red dashes, blue squares and green triangles
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.show()
```

![](http://matplotlib.org/_images/pyplot_three.png)

## 控制线条属性

线条有许多你可以设置的属性:`linewidth``dash style``antialiased`等,请参见`matplotlib.lines.Line2D`。 有几种方法可以设置线属性:

+   使用关键字参数:

    ```py
    plt.plot(x, y, linewidth=2.0)
    ```
    
+   使用`Line2D`实例的`setter`方法。 `plot`返回`Line2D`对象的列表,例如`line1,line2 = plot(x1,y1,x2,y2)`。 在下面的代码中,我们假设只有一行,返回的列表长度为 1。我们对`line`使用元组解构,得到该列表的第一个元素:

    ```py
    line, = plt.plot(x, y, '-')
    line.set_antialiased(False) # turn off antialising
    ```
    
+   使用`setp()`命令。 下面的示例使用 MATLAB 风格的命令来设置线条列表上的多个属性。 `setp`使用对象列表或单个对象透明地工作。 你可以使用 python 关键字参数或 MATLAB 风格的字符串/值对:

    ```py
    lines = plt.plot(x1, y1, x2, y2)
    # 使用关键字参数
    plt.setp(lines, color='r', linewidth=2.0)
    # 或者 MATLAB 风格的字符串值对
    plt.setp(lines, 'color', 'r', 'linewidth', 2.0)
    ```

下面是可用的`Line2D`属性。


| 属性 | 值类型 |
| --- | --- |
| `alpha` | 浮点值 |
W
fix  
wizardforcel 已提交
90 91
| `animated` | `[True / False]` |
| `antialiased or aa` | `[True / False]` |
W
3.1  
wizardforcel 已提交
92
| `clip_box` | `matplotlib.transform.Bbox` 实例 |
W
fix  
wizardforcel 已提交
93
| `clip_on` | `[True / False]` |
W
3.1  
wizardforcel 已提交
94 95 96
| `clip_path` | `Path` 实例和 `Transform` 实例,以及`Patch` |
| `color or c` | 任何 `matplotlib` 颜色 |
| `contains` | 命中测试函数 |
W
fix  
wizardforcel 已提交
97 98
| `dash_capstyle` | `['butt' / 'round' / 'projecting']` |
| `dash_joinstyle` | `['miter' / 'round' / 'bevel']` |
W
3.1  
wizardforcel 已提交
99 100 101 102
| `dashes` | 以点为单位的连接/断开墨水序列 |
| `data` | `(np.array xdata, np.array ydata)` |
| `figure` | `matplotlib.figure.Figure` 实例 |
| `label` | 任何字符串 |
W
fix  
wizardforcel 已提交
103
| `linestyle` or `ls` | `[ '-' / '--' / '-.' / ':' / 'steps' / ...]` |
W
3.1  
wizardforcel 已提交
104
| `linewidth` or `lw` | 以点为单位的浮点值 |
W
fix  
wizardforcel 已提交
105 106
| `lod` | `[True / False]` |
| `marker` | `[ '+' / ',' / '.' / '1' / '2' / '3' / '4' ]` |
W
3.1  
wizardforcel 已提交
107 108 109 110
| `markeredgecolor or mec` | 任何 `matplotlib` 颜色 |
| `markeredgewidth or mew` | 以点为单位的浮点值 |
| `markerfacecolor or mfc` | 任何 `matplotlib` 颜色 |
| `markersize or ms` | 浮点值 |
W
fix  
wizardforcel 已提交
111
| `markevery` | `[ None / 整数值 / (startind, stride) ]` |
W
3.1  
wizardforcel 已提交
112 113
| `picker` | 用于交互式线条选择 |
| `pickradius` | 线条的拾取选择半径 |
W
fix  
wizardforcel 已提交
114 115
| `solid_capstyle` | `['butt' / 'round' / 'projecting']` |
| `solid_joinstyle` | `['miter' / 'round' / 'bevel']` |
W
3.1  
wizardforcel 已提交
116
| `transform` | `matplotlib.transforms.Transform` 实例 |
W
fix  
wizardforcel 已提交
117
| `visible` | `[True / False]` |
W
3.1  
wizardforcel 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| `xdata` | `np.array` |
| `ydata` | `np.array` |
| `zorder` | 任何数值 |

要获取可设置的线条属性的列表,请以一个或多个线条作为参数调用`step()`函数

```py
In [69]: lines = plt.plot([1, 2, 3])

In [70]: plt.setp(lines)
  alpha: float
  animated: [True | False]
  antialiased or aa: [True | False]
  ...snip
```

W
3.3  
wizardforcel 已提交
134
## 处理多个图像和轴域
W
3.1  
wizardforcel 已提交
135

W
3.3  
wizardforcel 已提交
136
MATLAB 和 pyplot 具有当前图像和当前轴域的概念。 所有绘图命令适用于当前轴域。 函数`gca()`返回当前轴域(一个`matplotlib.axes.Axes`实例),`gcf()`返回当前图像(`matplotlib.figure.Figure`实例)。 通常,你不必担心这一点,因为它都是在幕后处理。 下面是一个创建两个子图的脚本。
W
3.1  
wizardforcel 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

```py
import numpy as np
import matplotlib.pyplot as plt

def f(t):
    return np.exp(-t) * np.cos(2*np.pi*t)

t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)

plt.figure(1)
plt.subplot(211)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')

plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()
```

![](http://matplotlib.org/_images/pyplot_two_subplots.png)

W
3.3  
wizardforcel 已提交
159
这里的`figure()`命令是可选的,因为默认情况下将创建`figure(1)`,如果不手动指定任何轴域,则默认创建`subplot(111)``subplot()`命令指定`numrows``numcols``fignum`,其中`fignum`的范围是从`1``numrows * numcols`。 如果`numrows * numcols <10`,则`subplot`命令中的逗号是可选的。 因此,子图`subplot(211)``subplot(2, 1, 1)`相同。 你可以创建任意数量的子图和轴域。 如果要手动放置轴域,即不在矩形网格上,请使用`axes()`命令,该命令允许你将`axes([left, bottom, width, height])`指定为位置,其中所有值都使用小数(0 到 1)坐标。 手动放置轴域的示例请参见[`pylab_examples`示例代码:`axes_demo.py`](http://matplotlib.org/examples/pylab_examples/axes_demo.html#pylab-examples-axes-demo),具有大量子图的示例请参见[`pylab_examples`示例代码:`subplots_demo.py`](http://matplotlib.org/examples/pylab_examples/subplots_demo.html#pylab-examples-subplots-demo)
W
3.1  
wizardforcel 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179

你可以通过使用递增图像编号多次调用`figure()`来创建多个图像。 当然,每个数字可以包含所需的轴和子图数量:

```py
import matplotlib.pyplot as plt
plt.figure(1)                # 第一个图像
plt.subplot(211)             # 第一个图像的第一个子图
plt.plot([1, 2, 3])
plt.subplot(212)             # 第一个图像的第二个子图
plt.plot([4, 5, 6])


plt.figure(2)                # 第二个图像
plt.plot([4, 5, 6])          # 默认创建 subplot(111)

plt.figure(1)                # 当前是图像 1,subplot(212)
plt.subplot(211)             # 将第一个图像的 subplot(211) 设为当前子图
plt.title('Easy as 1, 2, 3') # 子图 211 的标题
```

W
3.3  
wizardforcel 已提交
180
你可以使用`clf()`清除当前图像,使用`cla()`清除当前轴域。 如果你搞不清在幕后维护的状态(特别是当前的图像和轴域),不要绝望:这只是一个面向对象的 API 的简单的状态包装器,你可以使用面向对象 API(见[艺术家教程](http://matplotlib.org/users/artists.html#artist-tutorial))。
W
3.1  
wizardforcel 已提交
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

如果你正在制作大量的图像,你需要注意一件事:在一个图像用`close()`显式关闭之前,该图所需的内存不会完全释放。 删除对图像的所有引用,和/或使用窗口管理器杀死屏幕上出现的图像的窗口是不够的,因为在调用`close()`之前,`pyplot`会维护内部引用。

## 处理文本

`text()`命令可用于在任意位置添加文本,`xlabel()``ylabel()``title()`用于在指定的位置添加文本(详细示例请参阅[文本介绍](http://matplotlib.org/users/text_intro.html#text-intro))。

```py
import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

# 数据的直方图
n, bins, patches = plt.hist(x, 50, normed=1, facecolor='g', alpha=0.75)


plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()
```

![](http://matplotlib.org/_images/pyplot_text.png)

所有的`text()`命令返回一个`matplotlib.text.Text`实例。 与上面一样,你可以通过将关键字参数传递到`text`函数或使用`setp()`来自定义属性:

```py
t = plt.xlabel('my data', fontsize=14, color='red')
```

这些属性的更详细介绍请见[文本属性和布局](http://matplotlib.org/users/text_props.html#text-properties)


## 在文本中使用数学表达式

`matplotlib`在任何文本表达式中接受 TeX 方程表达式。 例如,要在标题中写入表达式,可以编写一个由美元符号包围的 TeX 表达式:

```py
plt.title(r'$\sigma_i=15$')
```

W
fix  
wizardforcel 已提交
227
标题字符串之前的`r`很重要 - 它表示该字符串是一个原始字符串,而不是将反斜杠作为 python 转义处理。 `matplotlib`有一个内置的 TeX 表达式解析器和布局引擎,并且自带了自己的数学字体 - 详细信息请参阅[编写数学表达式](http://matplotlib.org/users/mathtext.html#mathtext-tutorial)。 因此,你可以跨平台使用数学文本,而无需安装 TeX。 对于安装了 LaTeX 和`dvipng`的用户,还可以使用 LaTeX 格式化文本,并将输出直接合并到显示图像或保存的 postscript 中 - 请参阅[使用 LaTeX 进行文本渲染](http://matplotlib.org/users/usetex.html#usetex-tutorial)
W
3.1  
wizardforcel 已提交
228 229 230

## 标注文本

W
3.3  
wizardforcel 已提交
231
上面的`text()`基本命令将文本放置在轴域的任意位置。 文本的一个常见用法是对图的某些特征执行标注,而`annotate()`方法提供一些辅助功能,使标注变得容易。 在标注中,有两个要考虑的点:由参数`xy`表示的标注位置和`xytext`表示的文本位置。 这两个参数都是`(x, y)`元组。
W
3.1  
wizardforcel 已提交
232 233 234 235

![](http://matplotlib.org/_images/pyplot_annotate.png)


W
3.3  
wizardforcel 已提交
236
在此基本示例中,`xy`(箭头提示)和`xytext`(文本)都位于数据坐标中。 有多种其他坐标系可供选择 - 详细信息请参阅[标注文本](http://matplotlib.org/users/annotations_intro.html#annotations-tutorial)[标注轴域](http://matplotlib.org/users/annotations_guide.html#plotting-guide-annotation)。 更多示例可以在[`pylab_examples`示例代码:`annotation_demo.py`](http://matplotlib.org/examples/pylab_examples/annotation_demo.html#pylab-examples-annotation-demo)中找到。
W
3.1  
wizardforcel 已提交
237 238 239 240 241 242

## 对数和其它非线性轴

`matplotlib.pyplot`不仅支持线性轴刻度,还支持对数和对数刻度。 如果数据跨越许多数量级,通常会使用它。 更改轴的刻度很容易:

```py
W
fix  
wizardforcel 已提交
243
plt.xscale('log')
W
3.1  
wizardforcel 已提交
244 245 246 247 248 249 250 251
```

下面示例显示了四个图,具有相同数据和不同刻度的`y`轴。

```py
import numpy as np
import matplotlib.pyplot as plt

W
fix  
wizardforcel 已提交
252
# 生成一些区间 [0, 1] 内的数据
W
3.1  
wizardforcel 已提交
253 254 255 256 257
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))

W
3.3  
wizardforcel 已提交
258
# 带有多个轴域刻度的 plot
W
3.1  
wizardforcel 已提交
259 260
plt.figure(1)

W
fix  
wizardforcel 已提交
261
# 线性
W
3.1  
wizardforcel 已提交
262 263 264 265 266 267 268
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)


W
fix  
wizardforcel 已提交
269
# 对数
W
3.1  
wizardforcel 已提交
270 271 272 273 274 275 276
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)


W
fix  
wizardforcel 已提交
277
# 对称的对数
W
3.1  
wizardforcel 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
plt.subplot(223)
plt.plot(x, y - y.mean())
plt.yscale('symlog', linthreshy=0.05)
plt.title('symlog')
plt.grid(True)

# logit
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)

plt.show()
```

![](http://matplotlib.org/_images/pyplot_scales.png)

还可以添加自己的刻度,详细信息请参阅[向`matplotlib`添加新的刻度和投影](http://matplotlib.org/devel/add_new_projection.html#adding-new-scales)