有没有一种方法可以将matplotlib绘图旋转45度?

6
我正在寻找一种方法来旋转由matplotlib-pyplot(Python库)生成的图形45度(例如,将正方形形状旋转为菱形形状),请问是否能实现这一点?
我能想到的一种方法是对所有数据使用旋转过滤器,使其显示为旋转状态,但是图表本身仍将保持原始方向。
我希望能够使用matplotlib交互功能,因此保存为图像然后旋转不起作用。
此外,我希望使用pyplot函数来绘制图形,因此使用其他库进行绘制不是理想的解决方案。

2
我可以问一下为什么吗?如果是为了外部需求,你可以将图形保存为png格式,然后使用ImageMagick或相关程序旋转已保存的图像。 - tacaswell
2
@tcaswell 这是可能的,但我宁愿不保存到图形文件,因为我想要交互式使用matplotlib显示功能(平移、缩放、光标/数据协调等)。当然,在库中提供的解决方案会更加方便。 - Bitwise
5个回答

7

目前我找到的唯一部分解决方案是对图形进行旋转。这样可以使用matplotlib/pyplot提供的交互界面。

对于像plot()和scatter()这样的点形图,这很简单,但我特别想旋转imshow()。

此链接讨论了可能用于此任务的transform关键字,但它显然不起作用。

幸运的是,我找到了一个使用pcolormesh() 的解决方法。 pcolormesh() 绘制四边形网格并允许您指定角落坐标。因此,答案就是将相关变换应用于角落坐标。但请注意,pcolormesh() 的工作方式与imshow不同- 它会翻转您的矩阵。

我在网上没有看到这个解决方案,所以这里有一些关于旋转45度的pcolormesh()/imshow()的代码:

import matplotlib.pyplot as plt
import numpy as np

def pcolormesh_45deg(C):

    n = C.shape[0]
    # create rotation/scaling matrix
    t = np.array([[1,0.5],[-1,0.5]])
    # create coordinate matrix and transform it
    A = np.dot(np.array([(i[1],i[0]) for i in itertools.product(range(n,-1,-1),range(0,n+1,1))]),t)
    # plot
    plt.pcolormesh(A[:,1].reshape(n+1,n+1),A[:,0].reshape(n+1,n+1),np.flipud(C))

1
我知道这是一个很旧的帖子,但对我非常有用。我唯一的问题是如何使坐标位于容器的边缘而不是中心? - Phlya
C 是一个对称矩阵。 - user3521099

2

根据Bitwise的答案,您可以使用以下函数:

def pcolormesh_45deg(C, ax=None, xticks=None, xticklabels=None, yticks=None,
                     yticklabels=None, aspect='equal', rotation=45,
                     *args, **kwargs):
    import itertools

    if ax is None:
        ax = plt.gca()
    n = C.shape[0]
    # create rotation/scaling matrix
    t = np.array([[1, .5], [-1, .5]])
    # create coordinate matrix and transform it
    product = itertools.product(range(n, -1, -1), range(0, n + 1, 1))
    A = np.dot(np.array([(ii[1], ii[0]) for ii in product]), t)
    # plot
    ax.pcolormesh((2 * A[:, 1].reshape(n + 1, n + 1) - n),
                  A[:, 0].reshape(n + 1, n + 1),
                  np.flipud(C), *args, **kwargs)

    xticks = np.linspace(0, n - 1, n, dtype=int) if xticks is None else xticks
    yticks = np.linspace(0, n - 1, n, dtype=int) if yticks is None else yticks

    if xticks is not None:
        xticklabels = xticks if xticklabels is None else xticklabels
        for tick, label, in zip(xticks, xticklabels):
            ax.scatter(-n + tick + .5, tick + .5, marker='x', color='k')
            ax.text(-n + tick + .5, tick + .5, label,
                    horizontalalignment='right', rotation=-rotation)
    if yticks is not None:
        yticklabels = yticks if yticklabels is None else yticklabels
        for tick, label, in zip(yticks, yticklabels):
            ax.scatter(tick + .5, n - tick - .5, marker='x', color='k')
            ax.text(tick + .5, n - tick - .5, label,
                    horizontalalignment='left', rotation=rotation)

    if aspect:
        ax.set_aspect(aspect)
    ax.set_xlim(-n, n)
    ax.set_ylim(-n, n)
    ax.plot([-n, 0, n, 0., -n], [0, n, 0, -n, 0], color='k')
    ax.axis('off')
    return ax

1

那是可能的,不过我得使用mplot3d的绘图函数 - 希望它们拥有和pyplot函数相同的功能。谢谢。 - Bitwise
看了一下mplot3d,我发现它在二维绘图方面比pyplot受限制。因此,我更喜欢通过操作由pyplot创建的图来解决问题。 - Bitwise
只是好奇...为什么需要旋转?我感觉这里有一些数据可视化技巧可以学习。:] - altendky
1
altendky - 我有一个数据集,它为向量上的每对位置提供一个值。这被可视化为对称矩阵(或三角矩阵),将此矩阵定向的最自然方式是旋转45度,使对角线水平。这是显示此类数据的常见方式。 - Bitwise

0

你看过PIL吗?

这段代码将旋转一张图片。因此,如果你首先将绘图输出为图像文件,然后可以执行以下操作:

import Image
img = Image.open("plot.jpg")
img2 = img.rotate(45)
img2.show()
img2.save("rotate.jpg")

如果您不关心轴的旋转(或者您没有需要担心的轴),那么这个方法是可行的。 - mrchampe
请看我之前回答 tcaswell 的内容,我想要 matplotlib 中的交互式功能,所以这个对我不是很有用。 - Bitwise

0

这篇帖子建议您只能“手动”完成。

可以画出来,但您必须手动完成所有的转换/旋转,包括将轴绘制为Line2D实例和标签绘制为Text实例(例如,请参见存档中的“Scatter3D”示例)。当前没有简单、内置的方法来完成它。在轴处理的计划重构中,


谢谢,虽然那篇文章是2005年的,所以在此之后的7年中可能会有变化... - Bitwise
@ 我同意,希望你能找到一些东西,我很高兴错了 :) - root

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