matplotlib对齐twinx刻度线

时间:2013-11-27 13:22:38

标签: python matplotlib

是否可以制作具有两个独立y轴的绘图,使刻度线对齐?

下面是一半解决方案的示例。我使用twinx将y轴加倍,但是刻度标记没有对齐,并且网格线在图上形成了一个尴尬的图案。有没有办法让刻度线共享相同的位置,但对应不同的y值?在下面的示例中,我希望左侧5的刻度线与右侧6的刻度线位于同一垂直位置。

import numpy as np

a = np.random.normal(10, 3, size=20)
b = np.random.normal(20, 5, size=40)

fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.hist(a)
ax2.hist(b)

histograms

本练习的主要观点是使两条轴的网格线重叠。

3 个答案:

答案 0 :(得分:18)

您需要手动设置yticks,因为它们会自动计算,从而产生变化。添加这样的东西:

ax1.set_yticks(np.linspace(ax1.get_ybound()[0], ax1.get_ybound()[1], 5))
ax2.set_yticks(np.linspace(ax2.get_ybound()[0], ax2.get_ybound()[1], 5))

我们使用轴的边界之间的5个点的数组设置ytick位置。由于你有一个直方图,你可以在每种情况下将较低的值设置为零,并且你可能希望上限稍大一些,所以我会改为

ax1.set_yticks(np.linspace(0, ax1.get_ybound()[1]+1, 5))
ax2.set_yticks(np.linspace(0, ax2.get_ybound()[1]+1, 5))

给出一个情节(为了清晰起见,改变颜色和透明度(alpha)):

enter image description here

答案 1 :(得分:4)

我知道这很古老,但这将来可能会对某些人有所帮助。

我根据上述解决方案创建了一个函数,以确保标签最终不会包含很多小数位:

def calculate_ticks(ax, ticks, round_to=0.1, center=False):
    upperbound = np.ceil(ax.get_ybound()[1]/round_to)
    lowerbound = np.floor(ax.get_ybound()[0]/round_to)
    dy = upperbound - lowerbound
    fit = np.floor(dy/(ticks - 1)) + 1
    dy_new = (ticks - 1)*fit
    if center:
        offset = np.floor((dy_new - dy)/2)
        lowerbound = lowerbound - offset
    values = np.linspace(lowerbound, lowerbound + dy_new, ticks)
    return values*round_to

使用以下方式:

ax1.set_yticks(calculate_ticks(ax1, 10))
ax2.set_yticks(calculate_ticks(ax2, 10))

输出:

enter image description here

答案 2 :(得分:1)

迟来的答案是:对于那些在图中同时具有负值和正值的人,我发现的解决方案如下:

max1 = np.nanmax(ax1.get_ybound()) #in case you have nan values
max2 = np.nanmax(ax2.get_ybound())
ax1.set_yticks(np.linspace(-max1, max1, 5))
ax2.set_yticks(np.linspace(-max2, max2, 5))

这导致从零开始的对称轴距离,y轴上的零“线”对齐。

使用set_yticks的困难在于它在minmax之间计算,而不是min0max