【问题标题】:Matplotlib: orthographic projection of 3D data (in 2D plot)Matplotlib:3D 数据的正交投影(在 2D 图中)
【发布时间】:2022-01-02 04:53:56
【问题描述】:

我正在尝试使用正交投影在 2D 中绘制 3D 数据。以下是我正在寻找的部分内容:

import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
fig = plt.figure(figsize=(10,10),facecolor='white')
axs = [fig.add_subplot(223)]
axs.append(fig.add_subplot(224))#,sharey=axs[0]))
axs.append(fig.add_subplot(221))#,sharex=axs[0]))
rng = np.random.default_rng(12345)
values = rng.random((100,3))-.5
values[:,1] = 1.6*values[:,1]
values[:,2] = .5*values[:,2]

for ax,axis in zip(axs,['y','x','z']):
    axis1,axis2={'x':(1,2),'y':(0,2),'z':(0,1)}[axis]
    ax.add_patch(plt.Circle([0,0], radius=.2, color='pink',zorder=-20))
    ax.scatter(values[:,axis1],values[:,axis2])
axs[0].set_xlabel('x')
axs[2].set_ylabel('y')
axs[1].set_xlabel('y')
axs[0].set_ylabel('z')
fig.subplots_adjust(.08,.06,.99,.99,0,0)
plt.show()

这个情节和我尝试的修复存在一些问题:我需要“相等”的方面,以便圆圈实际上是圆形的。我还需要每个子图中的圆圈大小相同。最后,我希望空间得到优化(即,子图内部和子图之间的空白尽可能少)。

我尝试在子图之间共享轴,然后为每个轴执行 .axis('scaled').set_aspect('equal','box',share=True),但轴最终没有正确共享,并且每个子图中的圆圈最终大小不同。虽然它将子图裁剪为数据,但它在子图之间留下了很多空间。 .axis('equal').set_aspect('equal','datalim',share=True) 不共享轴会在子图中留下空白,使用共享轴会遗漏一些数据。

有什么办法让它工作吗?如果它可以在 matplotlib 3.4.3 上运行就完美了。

【问题讨论】:

    标签: python matplotlib 2d projection orthographic


    【解决方案1】:

    您可以为您的子图使用常见的xlimylim,并使用ax.set_aspect(aspect='equal', adjustable='datalim') 设置您的相等比率: 请参阅下面的完整代码:

    import numpy as np
    import matplotlib.pyplot as plt
    
    %matplotlib inline
    fig = plt.figure(figsize=(10,10),facecolor='white')
    
    axs = [fig.add_subplot(223)]
    axs.append(fig.add_subplot(224))#,sharey=axs[0]))
    axs.append(fig.add_subplot(221))#,sharex=axs[0]))
    rng = np.random.default_rng(12345)
    values = rng.random((100,3))-.5
    values[:,1] = 1.6*values[:,1]
    values[:,2] = .5*values[:,2]
    
    
    for ax,axis in zip(axs,['y','x','z']):
        axis1,axis2={'x':(1,2),'y':(0,2),'z':(0,1)}[axis]
        ax.add_patch(plt.Circle([0,0], radius=.2, color='pink',zorder=-20))
        ax.scatter(values[:,axis1],values[:,axis2])
        ax.set_xlim([np.amin(values),np.amax(values)])
        ax.set_ylim([np.amin(values),np.amax(values)])
        ax.set_aspect('equal', adjustable='datalim')
    
    axs[0].set_xlabel('x')
    axs[2].set_ylabel('y')
    axs[1].set_xlabel('y')
    axs[0].set_ylabel('z')
    fig.subplots_adjust(.08,.06,.99,.99,0,0)
    plt.show()
    

    输出给出:

    【讨论】:

    • 这很好!有什么方法可以改变坐标轴的大小来裁剪出空白区域?
    • 空格来自于设置xlim`` and the ylim. You can remove the lines ax.set_xlim([np.amin(values),np.amax(values)])`和ax.set_ylim([np.amin(values),np.amax(values)])。不同之处在于您的圈子看起来会有不同的大小。
    • 我的意思是类似于使用.set_aspect('equal', adjustable='box'),但具有适当的轴共享/具有相同的大小,并且理想情况下子图之间没有间隙。结果比我得到的要好,但仍然缺少它在轴内有很多不必要的空间。我会尝试看看是否可以使用 gridspec 来解决这个问题。
    • 我的情节上的子情节之间没有任何间隙吗?解决方案中的白色间距是使用adjustable='box' 形成的。尝试改用adjustable='datalim'(请参阅答案中的代码)
    【解决方案2】:

    我使用 gridspec 使它工作(我更改了 plot 的 scatter 以在视觉上确保没有数据被遗漏)。它需要对 figsize 进行一些调整,以真正最小化轴内的空白。感谢@jylls提供中间解决方案。

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.gridspec import GridSpec
    
    %matplotlib inline
    rng = np.random.default_rng(12345)
    values = rng.random((100,3))-.5
    values[:,1] = 1.6*values[:,1]
    values[:,2] = .5*values[:,2]
    
    fig = plt.figure(figsize=(10,8),facecolor='white')
    ranges = np.ptp(values,axis=0)
    gs = GridSpec(2, 2, None,.08,.06,.99,.99,0,0, width_ratios=[ranges[0], ranges[1]], height_ratios=[ranges[1], ranges[2]])
    axs = [fig.add_subplot(gs[2])]
    axs.append(fig.add_subplot(gs[3]))#,sharey=axs[0]))
    axs.append(fig.add_subplot(gs[0]))#,sharex=axs[0]))
    
    for ax,axis in zip(axs,['y','x','z']):
        axis1,axis2={'x':(1,2),'y':(0,2),'z':(0,1)}[axis]
        ax.add_patch(plt.Circle([0,0], radius=.2, color='pink',zorder=-20))
        ax.plot(values[:,axis1],values[:,axis2])
        ax.set_aspect('equal', adjustable='datalim')
    
    axs[0].set_xlabel('x')
    axs[2].set_ylabel('y')
    axs[1].set_xlabel('y')
    axs[0].set_ylabel('z')
    plt.show()
    

    【讨论】:

    • 很高兴听到您找到了您要找的东西!
    猜你喜欢
    • 2015-03-07
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 2017-01-12
    • 2011-11-25
    • 2014-06-09
    相关资源
    最近更新 更多