代码之家  ›  专栏  ›  技术社区  ›  Elliptica

不能在MaMattLIB 3D上获得轴对齐

  •  1
  • Elliptica  · 技术社区  · 6 年前

    我在试着做一个三维拟图。我很难让全轴显示与良好对齐的标签。我已经概述了下面的步骤。

    1)我可以设置y轴标签使用:

    yTicks = list(range(0,90,5)
    ax.set_yticks(range(len(yTicks)), True)
    

    enter image description here

    但是,正如您所看到的,这些标签排列得非常糟糕。它也与我实际定义的不匹配,应该是5,而不是10。

    2)如果我尝试使用 set_yticklabels 当然,对齐也会修复,但它只打印轴的一部分。下面是代码和图像:

    ax.set_yticklabels(yTicks, verticalalignment='baseline', horizontalalignment='left')

    enter image description here

    注意y轴是如何从80变为40的。

    3)如果我摆脱 True 在里面 set_yticks ,所有东西挤在一起:

    enter image description here

    4)最后,如果我同时使用 嵌套 设置标签 打电话 get_yticks() 在标签函数中,它几乎可以工作,但是您可以看到轴线延伸超出图形的“表面”:

    ax.set_yticks(range(len(yTicks)), True)
    ax.set_yticklabels(ax.get_yticks(), verticalalignment='baseline',
                   horizontalalignment='left')
    

    enter image description here

    5)下面是我的代码的一个更完整的版本供参考:

    plt.clf()
    
    ax = plt.axes(projection='3d')
    
    ax.bar3d(x,y,z, 
         1,1,[val*-1 if val != 0 else 0 for val in z])
    
    xTicks = list(range(0,25,2))
    yTicks = list(range(30,90,5))
    
    ax.set_zlim(0, 1)
    
    ax.set_xticks(range(len(xTicks)), True)
    ax.set_yticks(range(len(yTicks)), True)
    
    ax.set_xticklabels(ax.get_xticks(), 
                    verticalalignment='baseline',
                    horizontalalignment='left')
    
    ax.set_yticklabels(ax.get_yticks(), 
                    verticalalignment='baseline',
                    horizontalalignment='left')
    
    plt.savefig(file_path)
    

    我怎样才能让它显示我的全轴(0到90)的间隔5,并且它排列得很好?

    6) 更新 :根据下面与@importanceofbeingernest的对话,以下是我仍然使用以下代码遇到的问题:

    x=[15,28,20]; y=[30,50,80]; z=[1,1,1]
    
    plt.clf()
    
    ax = plt.axes(projection='3d')
    
    ax.bar3d(x,y,z, 
             1,1,[val*-1 if val != 0 else 0 for val in z])
    
    xTicks = list(range(0,25,2))
    yTicks = list(range(30,90,5))
    ax.set_xticks(xTicks)
    ax.set_yticks(yTicks)
    
    ax.set_yticklabels(ax.get_yticks(), 
                    verticalalignment='baseline',
                    horizontalalignment='left')
    
    ax.set_zlim(0, 1)
    
    plt.savefig(getSaveGraphPath(save_name))
    

    enter image description here

    2 回复  |  直到 6 年前
        1
  •  0
  •   ImportanceOfBeingErnest    6 年前

    如注释所示,您可以通过 ax.set_yticks

    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    
    x=[15,28,20]; y=[30,50,80]; z=[1,1,1]
    
    ax = plt.axes(projection='3d')
    
    ax.bar3d(x,y,z, 
         1,1,[val*-1 if val != 0 else 0 for val in z])
    
    
    yTicks = list(range(30,90,5))
    ax.set_yticks(yTicks)
    
    ax.set_yticklabels(ax.get_yticks(), 
                    verticalalignment='baseline',
                    horizontalalignment='left')
    
    ax.set_zlim(0, 1)
    
    plt.show()
    

    这将在y轴上显示所需的5个单位步数。

    enter image description here

        2
  •  0
  •   Elliptica    6 年前

    所以经过多次尝试和错误之后,在各种极限情况下,我唯一能得到适当渲染轴的图形的方法如下。我对它并不完全满意(注意上一个y-tick标签没有出现),但它是唯一一个在它们的记号旁边有数字的版本。我不得不让x和y的极限只有在数据没有超过它们的值时才有效,而z边界是一个硬极限。我不知道为什么这些排列都是必要的(这只是3D绘图的一个问题),但这是对我有效的解决方案:

    plt.clf()
    
    ax = plt.axes(projection='3d')
    
    # Need to force include fake NaN data at the axis limits to make sure labels
    # render correctly
    #
    # xLims and yLims create boundaries only if data doesn't stretch beyond them
    
    xstart, xend = xLims
    ystart, yend = yLims
    x = [xstart] + x + [xend]
    y = [ystart] + y + [yend]
    z = [numpy.nan] + z + [numpy.nan]
    
    # Plot graph
    
    ax.bar3d(x,y,z,1,1,[val*-1 if val != 0 else 0 for val in z])
    
    # Set z boundary (after graph creation)
    
    ax.set_zbound(zBounds)
    
    # Need to adjust labels slightly to make sure they align properly
    
    use_x_ticks = ax.get_xticks()
    
    ### ON SOME SYSTEMS, use_x_ticks = ax.get_xticks()[1:] is needed for correct alignment ###
    
    ax.set_xticklabels([int(x)  if x==int(x) else x for x in use_x_ticks],
                        horizontalalignment='right',
                        verticalalignment='baseline')
    
    ax.set_yticklabels([int(y) if y==int(y) else y for y in ax.get_yticks()],
                        verticalalignment='top')
    
    # Save graph
    
    plt.savefig(file_save_path)
    

    正如你在下面看到的,一切都很好地对齐:

    enter image description here