是否可以制作具有两个独立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)
本练习的主要观点是使两条轴的网格线重叠。
答案 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)):
答案 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))
输出:
答案 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
的困难在于它在min
和max
之间计算,而不是min
,0
,max
。