使用matplotlib转换整个坐标轴(或散点图)

5
我正在使用以下代码绘制一些数据均值和方差的变化。
import matplotlib.pyplot as pyplot
import numpy

vis_mv(data, ax = None):
    if ax is None: ax = pyplot.gca()
    cmap = pyplot.get_cmap()
    colors = cmap(numpy.linspace(0, 1, len(data)))

    xs = numpy.arange(len(data)) + 1
    means = numpy.array([ numpy.mean(x) for x in data ])
    varis = numpy.array([ numpy.var(x) for x in data ])
    vlim = max(1, numpy.amax(varis))

    # variance
    ax.imshow([[0.,1.],[0.,1.]],
        cmap = cmap, interpolation = 'bicubic',
        extent = (1, len(data), -vlim, vlim), aspect = 'auto'
    )
    ax.fill_between(xs, -vlim, -varis, color = 'white')
    ax.fill_between(xs, varis, vlim, color = 'white')

    # mean
    ax.plot(xs, means, color = 'white', zorder = 1)
    ax.scatter(xs, means, color = colors, edgecolor = 'white', zorder = 2)

    return ax

这个代码是完全正常的: enter image description here 但现在我想把这个可视化图表垂直地放置,作为另一个图表旁边的高级色条。我希望能够旋转整个坐标轴及其所有内容, 但我只找到了这个问题,它也没有一个确定的答案。因此,我尝试自己做如下操作:
from matplotlib.transforms import Affine2D

ax = vis_mv()
r = Affine2D().rotate_deg(90) + ax.transData

for x in ax.images + ax.lines + ax.collections:
    x.set_transform(r)

old = ax.axis()
ax.axis(old[2:4] + old[0:2])

这几乎可以解决问题(请注意,分散的点不再沿着白线摆动,并且没有按预期旋转)。遗憾的是,持有scatter结果的PathCollection并未按预期运作。尝试了一些方法后,我发现scatter具有某种偏移变换,这似乎相当于其他集合中的常规变换。
x = numpy.arange(5)
ax = pyplot.gca()
p0, = ax.plot(x)
p1 = ax.scatter(x,x)

ax.transData == p0.get_transform()           # True
ax.transData == p1.get_offset_transform()    # True

似乎我需要改变散点图的偏移变换,但是我没有找到任何允许我更改PathCollection上该变换的方法。而且,这将使我实际想要做的事情变得更加不方便。请问是否有可能改变偏移变换呢?谢谢!

@VBB 现在更清楚了吗? - Mr Tsjolder
1
一开始就把所有东西垂直绘制怎么样?imshowscatterplot可以直接使用,您可以使用ax.fill_betweenx进行着色。(PS:着色的好技巧) - VBB
@ImportanceOfBeingErnest 我提出这个问题的原因正是因为我想将整个图表旋转90度。因此,我认为合并这些问题可能是有意义的。我也觉得在问这个问题之前回答那个问题有点愚蠢。 - Mr Tsjolder
是的,但在这里你特别询问了一个问题,当使用另一个答案中的解决方案(不管是谁编写的)时会出现问题。因此,将它们链接起来肯定是有意义的,但我不认为这是重复的。 - ImportanceOfBeingErnest
1
@ImportanceOfBeingErnest 我更新了我的问题,以 1)提到其他问题的存在 2)集中于散点图 - Mr Tsjolder
显示剩余4条评论
1个回答

6

很遗憾,PathCollection没有.set_offset_transform()方法,但是可以访问私有的_transOffset属性,并将旋转变换设置到它上面。

import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
from matplotlib.collections import PathCollection
import numpy as np; np.random.seed(3)

def vis_mv(data, ax = None):
    if ax is None: ax = plt.gca()
    cmap = plt.get_cmap()
    colors = cmap(np.linspace(0, 1, len(data)))

    xs = np.arange(len(data)) + 1
    means = np.array([ np.mean(x) for x in data ])
    varis = np.array([ np.var(x) for x in data ])
    vlim = max(1, np.amax(varis))

    # variance
    ax.imshow([[0.,1.],[0.,1.]],
        cmap = cmap, interpolation = 'bicubic',
        extent = (1, len(data), -vlim, vlim), aspect = 'auto'  )
    ax.fill_between(xs, -vlim, -varis, color = 'white')
    ax.fill_between(xs, varis, vlim, color = 'white')

    # mean
    ax.plot(xs, means, color = 'white', zorder = 1)
    ax.scatter(xs, means, color = colors, edgecolor = 'white', zorder = 2)

    return ax

data = np.random.normal(size=(9, 9))
ax  = vis_mv(data)


r = Affine2D().rotate_deg(90)

for x in ax.images + ax.lines + ax.collections:
    trans = x.get_transform()
    x.set_transform(r+trans)
    if isinstance(x, PathCollection):
        transoff = x.get_offset_transform()
        x._transOffset = r+transoff

old = ax.axis()
ax.axis(old[2:4] + old[0:2])


plt.show()

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接