Matplotlib:变换

日期2010-06-16(最后修改),2006-01-22(创建)

无论何时将坐标传递给 matplotlib,都会出现一个问题,即您指的是哪种坐标。考虑以下示例

In [ ]
axes.text(x,y, "my label")

在坐标 x,y 处向轴添加一个标签“my label”,或者更准确地说:文本放置在数据点 (x,y) 的理论位置。因此,我们称之为“数据坐标”。但是,还可以考虑其他坐标。例如,您可能希望将标签放在图形的正中间。如果您使用上述方法指定它,那么您需要确定 x 和 y 的最小值和最大值以确定中间位置。但是,使用变换,您可以简单地使用

In [ ]
axes.text(0.5, 0.5, "middle of graph", transform=axes.transAxes)

有四种内置变换,您应该了解它们(让 ax 是一个 Axes 实例,fig 是一个 Figure 实例)

In [ ]
matplotlib.transforms.identity_transform()  # display coords
ax.transData     # data coords
ax.transAxes     # 0,0 is bottom,left of axes and 1,1 is top,right
fig.transFigure  # 0,0 is bottom,left of figure and 1,1 is top,right

这些变换可用于任何类型的 Artist,而不仅仅是文本对象。

ax.text 的默认变换是 ax.transData,fig.text 的默认变换是 fig.transFigure。

当然,您可以定义更通用的变换,例如 matplotlib.transforms.Affine,但上面列出的四种变换在许多应用程序中出现。

xy_tup() 函数已不再使用。请参阅 Matplotlib 官方文档 http://matplotlib.sourceforge.net/users/transforms_tutorial.html 以获取更多参考。

示例:类似注释的刻度标签

如果您发现 Matplotlib 的内置刻度标签不足以满足您的需求,可以使用变换来实现类似的功能。以下示例在刻度标签下方绘制注释,并使用变换来确保注释的 x 坐标与绘图的 x 坐标一致,但 y 坐标位于固定位置,与绘图的比例无关。

In [ ]
import matplotlib as M
import Numeric as N
import pylab as P
blend = M.transforms.blend_xy_sep_transform

def doplot(fig, subplot, function):
    ax = fig.add_subplot(subplot)
    x = N.arange(0, 2*N.pi, 0.05)
    ax.plot(x, function(x))

    trans = blend(ax.transData, ax.transAxes)

    for x,text in [(0.0, '|'), (N.pi/2, r'$\rm{zero\ to\ }\pi$'),
                   (N.pi, '|'), (N.pi*1.5, r'$\pi\rm{\ to\ }2\pi$'),
                   (2*N.pi, '|')]:
        ax.text(x, -0.1, text, transform=trans,
                horizontalalignment='center')

fig = P.figure()
doplot(fig, 121, N.sin)
doplot(fig, 122, lambda x: 10*N.sin(x))
P.show()

示例:向数据坐标添加像素偏移量

有时您希望指定标签显示在对应数据点的固定像素偏移量处,无论缩放如何。以下是一种方法;尝试在交互式后端运行此代码,并缩放和平移图形。

此方法的工作原理是首先对 `transData` 进行浅拷贝,然后向其添加偏移量。所有变换都可以具有偏移量,可以通过 `set_offset` 进行修改,并且进行拷贝是为了避免修改数据本身的变换。较新版本的 matplotlib(目前仅限 svn 版本)具有 `offset_copy` 函数,可以自动执行此操作。

In [ ]
import matplotlib
import matplotlib.transforms
from pylab import figure, show

# New enough versions have offset_copy by Eric Firing:
if 'offset_copy' in dir(matplotlib.transforms):
    from matplotlib.transforms import offset_copy
    def offset(ax, x, y):
        return offset_copy(ax.transData, x=x, y=y, units='dots')
else: # Without offset_copy we have to do some black transform magic
    from matplotlib.transforms import blend_xy_sep_transform, identity_transform
    def offset(ax, x, y):
        # This trick makes a shallow copy of ax.transData (but fails for polar plots):
        trans = blend_xy_sep_transform(ax.transData, ax.transData)
        # Now we set the offset in pixels
        trans.set_offset((x,y), identity_transform())
        return trans

fig=figure()
ax=fig.add_subplot(111)

# plot some data
x = (3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3)
y = (2,7,1,8,2,8,1,8,2,8,4,5,9,0,4,5)
ax.plot(x,y,'.')

# add labels
trans=offset(ax, 10, 5)
for a,b in zip(x,y):
    ax.text(a, b, '(%d,%d)'%(a,b), transform=trans)

show()

章节作者:AndrewStraw、Unknown[115]、Unknown[77]、GaelVaroquaux、Unknown[116]