Matplotlib 1.5 新特性 (2015年10月29日)#

注意

matplotlib 1.5 支持 Python 2.7, 3.4 和 3.5

交互式面向对象(OO)用法#

所有的 Artist 对象现在都会跟踪其内部状态是否已更改但尚未通过调用 draw 反映在显示器中(即“过时 (stale)”状态)。因此,可以在交互式会话中通过程序确定给定的 Figure 是否需要重新绘制。

为了方便交互式使用,pyplot 中新增了 draw_all 方法,该方法将重新绘制所有处于“过时(stale)”状态的图形。

为了使交互式使用更加便利,matplotlib 现在会在 IPython 的 'post_execute' 事件中或在标准 Python REPL 的 displayhook 中注册一个函数,以便在控制权返回给 REPL 之前自动调用 plt.draw_all。这可以确保绘制命令被推迟并仅调用一次。

其结果是,对于处于交互模式(使用 plt.ion())下的交互式后端(包括 %matplotlib notebook

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ln, = ax.plot([0, 1, 4, 9, 16])
plt.show()
ln.set_color('g')

将自动更新图表为绿色。随后对 Artist 对象的任何修改也会同样自动更新。

这是对 pyplot 内部进行更广泛的整合和简化迈出的第一步。

使用类似 pandas DataFrame 的带标签数据#

现在,以数组作为输入的绘图方法也可以处理带标签的数据,并可以对这些数据进行解包。

这意味着以下两个示例将生成相同的图表

示例

df = pandas.DataFrame({"var1":[1,2,3,4,5,6], "var2":[1,2,3,4,5,6]})
plt.plot(df["var1"], df["var2"])

示例

plt.plot("var1", "var2", data=df)

这适用于大多数期望将数组/序列作为输入的绘图方法。data 可以是任何支持通过 __getitem__ 且可使用字符串键访问类数组(array-like)值的对象(如 dictpandas.DataFrameh5py 等)。

除此以外,还进行了一些其他更改,这使得使用带标签数据(例如 pandas.Series)变得更加容易

  • 对于带有 label 关键字参数的绘图方法,其中一个数据输入将被指定为标签来源。如果用户没有提供 label,则会内省该值对象以获取标签(目前通过查找 name 属性)。如果该值对象没有 name 属性,但被指定为 data 关键字参数中的键,则将使用该键。在上述示例中,这会在两种情况下都导致隐式的 label="var2"

  • 如果没有提供 x 参数,plot() 现在将使用 Series 的索引,而不是 np.arange(len(y))

在 rcParams 中添加了 axes.prop_cycle#

这是现已弃用的 axes.color_cycle 参数的更通用形式。现在,我们不仅可以循环颜色,还可以循环线型、阴影线(hatches)以及几乎任何其他 artist 属性。Cycler 记法用于定义属性循环。将多个 cycler 相加就像是将两个或多个属性循环 zip 打包在一起

axes.prop_cycle: cycler('color', 'rgb') + cycler('lw', [1, 2, 3])

你甚至可以对 cycler 进行乘法运算,这类似于对两个或多个属性循环使用 itertools.product

../../_images/sphx_glr_color_cycle_001.png

新颜色表(Colormaps)#

提议作为新默认颜色的全部四种颜色表均已可用,分别为 'viridis'(2.0 中的新默认值)、'magma''plasma''inferno'

(源码, 2x.png, png)

样式#

添加了几个新样式,其中包括来自 Seaborn 项目的许多样式。此外,为了准备即将发布的 2.0 样式变更版本,新增了 'classic'(经典)和 'default'(默认)样式。在此版本中,'default' 和 'classic' 样式是完全相同的。现在就在您的脚本中使用它们,可以帮助确保在未来升级 matplotlib 时平稳过渡,以便您在准备就绪时能顺利升级到炫酷的新默认值!

import matplotlib.style
matplotlib.style.use('classic')

'default' 样式将为您提供 matplotlib 的最新绘图样式

matplotlib.style.use('default')

后端#

新后端选择#

环境变量 MPLBACKEND 现在可用于设置 matplotlib 后端。

wx 后端已更新#

wx 后端现在可以同时与 wxPython classic 和 Phoenix 一起使用。

wxPython classic 的版本必须至少为 2.8.12,且可在 Python 2.x 上运行。截至 2015 年 5 月,尚未发布 wxPython Phoenix 的正式版本,但当前的快照版本将可在 Python 2.7+ 和 3.4+ 上运行。

如果您安装了多个版本的 wxPython,则由用户代码负责设置 wxPython 版本。如何操作已在示例 Embed in wx #2 开头的注释中进行了说明。

配置 (rcParams)#

添加了一些参数,改进了其他参数。

参数

描述

xaxis.labelpad, yaxis.labelpad

mplot3d 现在支持这些属性,其默认值为 rcParams["axes.labelpad"](默认值:4.0

rcParams["axes.labelpad"](默认值:4.0

轴与标签之间的默认间距

rcParams["errorbar.capsize"](默认值:0.0

误差棒端帽的默认长度

rcParams["xtick.minor.visible"](默认值:False),rcParams["ytick.minor.visible"](默认值:False

次要 x/y 刻度线的默认可见性

rcParams["legend.framealpha"](默认值:0.8

图例边框盒的默认透明度

rcParams["legend.facecolor"](默认值:'inherit'

图例边框盒的默认背景色(或自 rcParams["axes.facecolor"](默认值:'white''inherit' 继承)

rcParams["legend.edgecolor"](默认值:'0.8'

图例边框盒的默认边框颜色(或自 rcParams["axes.edgecolor"](默认值:'black''inherit' 继承)

rcParams["figure.titlesize"](默认值:'large'

图表总标题(suptitle)的默认字体大小

rcParams["figure.titleweight"](默认值:'normal'

图表总标题(suptitle)的默认字体粗细

rcParams["image.composite_image"](默认值:True

保存时矢量图形后端是否应将多张图像合并为单张图像。当需要在 Inkscape 或其他程序中进一步编辑文件时很有用。

rcParams["markers.fillstyle"](默认值:'full'

标记的默认填充样式。可能的值有 'full'(默认)、'left''right''bottom''top''none'

rcParams["toolbar"](默认值:'toolbar2'

添加了 'toolmanager' 作为有效值,以启用实验性的 ToolManager 功能。

微件(Widgets)#

选择器的激活状态#

现在所有选择器都实现了 set_activeget_active 方法(在访问 active 属性时也会被调用),以便正确更新和查询它们是否处于活动状态。

ignoreset_activeget_active 方法移至基类 Widget#

将子类中的重复方法提升到父类中,以避免代码重复。

为 MultiCursor 添加启用/禁用功能#

MultiCursor 对象在创建后可以被禁用(和启用),而无需销毁该对象。示例

multi_cursor.active = False

改进的 RectangleSelector 和新的 EllipseSelector 微件#

添加了一个 interactive 关键字,用于在绘制形状后启用可见的控制手柄以操作形状。

添加了用于以下操作的键盘修饰键

  • 移动现有形状(默认键 = 'space')

  • 使形状变为正方形(默认 'shift')

  • 将起点作为形状的中心(默认 'control')

  • 正方形和居中操作可以结合使用

允许 Artist 在光标处显示像素数据#

为 artist 添加了 get_cursor_dataformat_cursor_data 方法,这些方法可用于在状态栏的光标显示中添加 z轴数据。还为 Image 添加了实现。

新绘图功能#

自动换行文本#

为 Text 添加了关键字参数 "wrap",该参数在绘制时会自动对长文本行进行换行。适用于任何旋转的文本、不同的对齐模式,以及作为标签或标题的文本。此换行基于 Figure 边缘,而不是 Axes 边缘。

(源码, 2x.png, png)

等高线图拐角遮罩#

Ian Thomas 重写了计算等高线的 C++ 代码,以增加对拐角遮罩(corner masking)的支持。这由 contour()contourf() 函数中新增的关键字参数 corner_mask 控制。以前的行为(现在可通过使用 corner_mask=False 获得)是单个遮罩点会完全遮罩接触该点的所有四个象限。使用 corner_mask=True 获得的新行为则仅遮罩接触该点的象限拐角;包含三个未遮罩点的任何三角形拐角仍会照常绘制等高线。如果未指定 corner_mask 关键字参数,则默认值从 rcParams 中获取。

../../_images/sphx_glr_contour_corner_mask_001.png

基本统一了 Line2DPatchCollection 的线型(linestyle)#

对 Lines、Patches 和 Collections 线型的处理已得到统一。现在,它们都支持使用简短符号(如 "--")以及完整名称(如 "dashed")来定义线型。此外,所有使用 Line2DPatchCollection 的方法现在也支持使用虚线模式(dash pattern,如 (0., [3., 3.]))进行定义。

图例标记顺序#

增加了在图例框中使用 markerfirst 关键字将标签放置在标记之前的能力

支持 PolyCollection 和 stackplot 的图例#

PolyCollection 添加了 legend_handler,并为 stackplot() 添加了 labels 参数。

在 mplot3d 矢量图(quiver plot)中支持备用锚点(pivots)#

quiver 添加了 pivot 关键字参数,用于控制矢量线旋转围绕的中心点(锚点)。这也决定了箭头在矢量线上的放置位置。

Logit 对数几率刻度#

添加了对 'logit' 轴刻度的支持,这是一种非线性转换

\[x -> \log10(x / (1-x))\]

适用于介于 0 到 1 之间(不含两端)的数据。

为 fill_between 添加 step 关键字参数#

Axes.fill_between 添加了 step 关键字参数,以允许在使用 'step'(阶梯)绘制样式绘制的线之间进行填充。step 的值与 Axes.stepwhere 关键字参数匹配。关键字参数名称的不对称性虽然不尽理想,但 Axes.fill_between 已经具有了一个 where 关键字参数。

这对于绘制预先分箱的直方图特别有用。

正方形图#

实现了正方形图功能,作为 axis 函数中的一个新参数。当指定参数 'square' 时,将设置等比例缩放,并设置限制使得 xmax-xmin == ymax-ymin

(源码, 2x.png, png)

更新了 figimage 以接受可选的 resize 参数#

添加了使用 plt.figimage(X, resize=True) 绘制简单二维数组(2D-Array)的能力。这对于在没有坐标轴(Axes)或图像周围留白的情况下绘制简单的二维数组非常有用。

(源码, 2x.png, png)

更新后的 Figure.savefig() 现在可以使用图表的 dpi#

添加了通过使用 dpi='figure' 以与屏幕上图表相同的 dpi 保存图表的支持。

示例

f = plt.figure(dpi=25)  # dpi set to 25
S = plt.scatter([1,2,3],[4,5,6])
f.savefig('output.png', dpi='figure')  # output savefig dpi set to 25 (same as figure)

更新了 Table 以控制边缘可见性#

添加了在表格中切换线条可见性的功能。该功能添加到了 pyplot.table 工厂函数中,使用的关键字参数为 "edges"。其值可以是字符串 "open"、"closed"、"horizontal"、"vertical",或字母 "L"、"R"、"T"、"B" 的组合,分别代表左、右、上和下。

示例

table(..., edges="open")  # No line visible
table(..., edges="closed")  # All lines visible
table(..., edges="horizontal")  # Only top and bottom lines visible
table(..., edges="LT")  # Only left and top lines visible.

plot_wireframe 中对零级 r/cstride 的支持#

Adam Hughes 为 mplot3d 的 plot_wireframe 添加了支持,以仅绘制行或列线图。

(源码, 2x.png, png)

使用标签绘制 bar 和 barh 柱状图#

barbarh 添加了关键字参数 tick_label,以支持为每个柱子带有文本标签地绘制柱状图。

(源码, 2x.png, png)

向 pie 饼图添加了 center 和 frame 关键字参数#

这些参数控制饼图中心的位置以及是否显示坐标轴(Axes)框架。

修复了三维填充等高线图的多边形渲染问题#

由于在 PolyCollectionPoly3DCollection 之间丢失了路径信息,生成带多个孔洞多边形的某些 3D 填充等高线图会产生不正确的渲染。为此添加了一个函数 set_verts_and_codes(),以便保留路径信息以进行正确的渲染。

稠密颜色栏已被栅格化#

矢量文件格式(pdf, ps, svg)对于许多类型的绘图元素都是高效的,但对于某些元素,它们可能会导致文件过大,甚至产生渲染伪影,这取决于屏幕显示所使用的渲染器。对于显示大量渐变色的颜色栏(这是最常见的情况)来说,这就是个问题。现在,如果颜色栏显示 50 种或更多颜色,它在矢量后端中将被栅格化。

DateFormatter strftime#

DateFormatter__call__ 方法将使用传递给格式化器构造函数的格式字符串来格式化 datetime.datetime 对象。与 datetime.datetime.strftime() 不同,此方法接受年份在 1900 年之前的日期时间。

用于文本的 Artist 级别 {get,set}_usetex#

Text 对象添加了 {get,set}_usetex 方法,允许在 artist 级别控制使用 LaTeX 渲染还是内部 mathtex 渲染。

Axes.remove() 如预期般工作#

与添加到 Axes 的 artist 类似,Axes 对象现在也可以通过 remove() 从其图表中移除。

定位器(Locators)set_params() 函数内的 API 一致性修复#

set_params() 函数(用于设置 Locator 类型实例中的参数)现在对所有 Locator 类型均可用。该实现还通过严格定义用户可以设置的参数来防止不安全的使用。

要使用它,可在包含所需参数的 Locator 实例上调用 set_params()

loc = matplotlib.ticker.LogLocator()
# Set given attributes for loc.
loc.set_params(numticks=8, numdecs=8, subs=[2.0], base=8)
# The below will error, as there is no such parameter for LogLocator
# named foo
# loc.set_params(foo='bar')

日期定位器#

日期定位器(派生自 DateLocator)现在实现了 tick_values 方法。这是所有派生自 Locator 的定位器都应具有的。

现在无需创建坐标轴即可轻松使用日期定位器

from datetime import datetime
from matplotlib.dates import YearLocator
t0 = datetime(2002, 10, 9, 12, 10)
tf = datetime(2005, 10, 9, 12, 15)
loc = YearLocator()
values = loc.tick_values(t0, tf)

OffsetBox 现在支持裁剪(clipping)#

Artist 通过 DrawingAreaTextArea 在类型为 OffsetBox 的对象上进行绘制。TextArea 会计算文本所需的空间,因此文本始终在边界内,这方面没有变化。

然而, DrawingArea 作为零个或多个在其中绘制且可能超出边界的 Artist 的父级。现在,子 Artist 可以被裁剪到 DrawingArea 的边界内。

tight_layout 现在会考虑 OffsetBox#

当调用 tight_layout()Figure.tight_layoutGridSpec.tight_layout() 时,锚定在坐标轴外部的 OffsetBox 不会被裁剪掉。在存在多个子图的情况下,OffsetBox 也不会被其他坐标轴重叠。

多页 PDF (PdfPages) 中支持逐页 PDF 注释#

向 PdfPages 类添加了一个新方法 attach_note(),允许在包含多页图表的 PDF 中的页面上添加简单的文本注释。在具有此功能的阅读器(如 Adobe Reader、OSX Preview、Skim 等)中,新注释在 PDF 注释列表中是可见的。默认情况下,注释本身保持在页面之外,以防止其出现在打印件中。

需要在调用 savefig 之前调用 PdfPages.attach_note,以便将其添加到正确的图表中。

更新了 fignum_exists 以接受图表名称#

添加了使用图表名称(而不仅仅是图表编号)来检查图表是否存在的能力。示例

figure('figure')
fignum_exists('figure') #true

工具管理器(ToolManager)#

Federico Ariza 编写了新的 ToolManager,用于替代 NavigationToolbar2

ToolManager 提供了一种看待用户与图表交互的新方式。以前我们使用带有自身工具(如 zoom/pan/home/save/...)的 NavigationToolbar2,同时还有诸如 yscale/grid/quit/.... 等快捷键。ToolManager 将所有这些操作重新定位为“工具”(位于 backend_tools 中),并定义了一种访问/触发/重新配置它们的方法。

工具栏(Toolbars)被替换为 ToolContainerBase,它们仅仅是用于触发工具的 GUI 界面。不过不用担心,默认后端包含一个名为 toolbarToolContainerBase

注意

目前,我们发布此功能主要用于收集反馈,在另行通知之前应将其视为实验性功能,因为后续可能会发生 API 更改。目前 ToolManager 仅适用于 GTK3 和 Tk 后端。请确保您使用的是其中之一。其他后端的移植很快就会推出。

要激活 ToolManager,请在文件顶部包含以下内容

>>> matplotlib.rcParams['toolbar'] = 'toolmanager'

与 ToolContainer 交互#

最重要的功能是能够轻松重新配置 ToolContainer(又名工具栏)。例如,如果我们想移除“前进(forward)”按钮,我们只需执行以下操作。

>>> fig.canvas.manager.toolmanager.remove_tool('forward')

现在,如果您想通过程序触发“主页(home)”按钮

>>> fig.canvas.manager.toolmanager.trigger_tool('home')

用于 ToolManager 的新工具#

可以向 ToolManager 添加新工具

一个打印 "You're awesome" 的极简工具如下:

from matplotlib.backend_tools import ToolBase
class AwesomeTool(ToolBase):
    def trigger(self, *args, **kwargs):
        print("You're awesome")

要将此工具添加到 ToolManager

>>> fig.canvas.manager.toolmanager.add_tool('Awesome', AwesomeTool)

如果我们想为该工具添加一个快捷键("d")

>>> fig.canvas.manager.toolmanager.update_keymap('Awesome', 'd')

要将其添加到工具栏的 'foo' 组中

>>> fig.canvas.manager.toolbar.add_tool('Awesome', 'foo')

还有第二类工具,即“可切换工具(Toggleable Tools)”,它们与我们的基础工具几乎相同,只是它们属于一个组,并且在该组内互斥。对于派生自 ToolToggleBase 的工具,有两个基本方法 enabledisable,每当它被切换时,这两个方法就会被自动调用。

完整的示例位于 工具管理器(Tool Manager)

cbook.is_sequence_of_strings 可识别字符串对象#

这主要是 pandas 存储字符串序列的方式

import pandas as pd
import matplotlib.cbook as cbook

a = np.array(['a', 'b', 'c'])
print(cbook.is_sequence_of_strings(a))  # True

a = np.array(['a', 'b', 'c'], dtype=object)
print(cbook.is_sequence_of_strings(a))  # True

s = pd.Series(['a', 'b', 'c'])
print(cbook.is_sequence_of_strings(s))  # True

此前,最后两个 print 返回 false。

plot 指令新增 close-figs 参数#

Matplotlib 有一个名为 plot_directive 的 Sphinx 扩展,用于创建要包含在 Sphinx 文档中的图表。Matplotlib 1.5 为 plot 指令添加了一个新选项 close-figs,该选项在创建新图表之前会关闭所有以前的图表窗口。这可以帮助避免在使用 plot_directive 时出现一些意外的重复图表。

支持将 URL 字符串参数传递给 imread#

现在,imread() 函数接受指向远程 PNG 文件的 URL 字符串。这避免了直接生成 HTTPResponse 对象。

IPython notebook 中动画的显示钩子#

Animation 实例获得了 _repr_html_ 方法,以支持在 notebook 中内联显示动画。用于显示的方法由 animation.html rc 参数控制,该参数目前支持 nonehtml5 值。none 是默认值,不进行显示。html5 会将动画转换为 h264 编码的视频,并将其直接嵌入 notebook 中。

不想使用 _repr_html_ 显示钩子的用户也可以手动调用 to_html5_video 方法来获取 HTML,并使用 IPython 的 HTML 显示类进行显示

from IPython.display import HTML
HTML(anim.to_html5_video())

用于构建的带前缀 pkg-config#

对 pkg-config 的处理已得到修复,现在可以通过环境变量 PKG_CONFIG 来设置它。如果您的工具链带有前缀,这一点将非常重要。其操作方法与在构建前设置 CCCXX 类似。示例如下

export PKG_CONFIG=x86_64-pc-linux-gnu-pkg-config