问题
我有一个带有2个y轴的图,每个轴对应一组线。实线对应于左y轴,虚线对应于右y轴。我也有一个图例,我希望它只使用实线作为键,因为虚线具有相同的标签,具体取决于它们的颜色。
问题是当我绘制实线的图例,然后是虚线的代码时,网格线通过图例显示。我需要为两个轴指定网格线,因为它们不会以其他方式显示,如果我将图例移动到虚线,它会使用虚线作为键。我也不想改变我的绘图顺序。
代码和情节
#Plot
x= np.arange(0,3)
fig,ax = plt.subplots(figsize=(6,6))
#DOD
dod1 = ax.plot(x, ctrl_dod, color='r', label='CTRL' )
dod2 = ax.plot(x, mfkc_dod, color='#e68a00', label='MFKC' )
dod3 = ax.plot(x, gses_dod, color='green', label='GSES' )
dod4 = ax.plot(x, gses3_dod, color='blue', label='GSES-3')
dod5 = ax.plot(x, gses4_dod, color='purple', label='GSES-4')
dod6 = ax.plot(x, mera_dod, color='brown', label='MERRA2')
ax.xaxis.grid(True)
ax.set_ylim([0.02,0.044])
ax.set_yticks(np.arange(0.02,0.045,0.004))
ax.set_xlabel('Month')
ax.set_ylabel('Dust Optical Depth (550 nm)')
ax.set_title('Global Mean DOD and DCM')
legend = ax.legend()
legend.get_frame().set_facecolor('white')
#DCM
ax2 = ax.twinx()
dcm1 = ax2.plot(x, ctrl_dcm*1e6, color='r', linestyle='--', label='CTRL' )
dcm2 = ax2.plot(x, mfkc_dcm*1e6, color='#e68a00', linestyle='--', label='MFKC' )
dcm3 = ax2.plot(x, gses_dcm*1e6, color='green', linestyle='--', label='GSES' )
dcm4 = ax2.plot(x, gses3_dcm*1e6, color='blue', linestyle='--', label='GSES-3')
dcm5 = ax2.plot(x, gses4_dcm*1e6, color='purple', linestyle='--', label='GSES-4')
dcm6 = ax2.plot(x, mera_dcm*1e6, color='brown', linestyle='--', label='MERRA2')
ax2.xaxis.grid(True)
ax2.yaxis.grid(True)
ax2.set_xlabel('Month')
ax2.set_ylabel('Dust Column Mass (mg m-2)')
#Limits
axes = plt.gca()
axes.set_xlim([-0.25,2.25])
#Labels
axes.set_xticks(x)
axes.set_xticklabels(['June','July','August'])
#Save
pylab.savefig('dod+dcm.png')
问题
我怎么能
a)让图例键使用实线和
b)具有不透明白色图例的背景?
答案 0 :(得分:4)
您可以为第二个轴创建图例,但使用第一个轴的手柄。
h, l = ax.get_legend_handles_labels()
legend = ax2.legend(h,l, facecolor="white")
答案 1 :(得分:0)
我来到这里,因为我遇到了同样的问题,但想要两个单独的图例,每个双轴一个。
@ImportanceOfBeingErnest 提供的已接受答案不再有效,因为它只允许将一个图例附加到 ax2
。
在这种情况下,@ImportanceOfBeingErnest 在 https://github.com/matplotlib/matplotlib/issues/3706#issuecomment-378407795 处也提供了替代解决方案。
我将它们都转换为一个我通常在这种情况下使用的函数,并认为在此处提供它会很有用:
def legend_to_ax( ax, ax_placein=None, method=2, **kwargs ):
""" Wrapper around ax.legend(**kwargs) which permits to have the legend
placed in the axis ax_placein.
This is useful when drawing legends for multiple axes, e.g.produced with
ax2 = ax1.twinx(), in order to have all legends on top of all axes.
In this case provide the uppermost axis, e.g. ax2 here, as ax_placein.
Args:
- ax : axis for which the legend is created
- ax_placein : axis which the legend should be placed in (optional)
- method : method by which to handle the placement of the legend in
ax_placein.
method=1 ... based on
https://stackoverflow.com/a/45336414/7042795
This method fails when multiple legends should
be added to ax_placein.
method=2 ... based on
https://github.com/matplotlib/matplotlib/issues/3706#issuecomment-378407795
This adds the legend as an artist to ax_placein
making it no longer appear via ax.get_legend().
Instead parse ax_placein.artists()
- **kwargs : kwargs of ax.legend()
Returns:
- leg : legend handle
"""
if ax_placein is None:
leg = ax.legend(**kwargs)
elif method==1:
# based on https://stackoverflow.com/a/45336414/7042795
h, l = ax.get_legend_handles_labels()
if ax_placein is not None:
ax = ax_placein
leg = ax.legend( h, l, **kwargs)
elif method==2:
# based on https://github.com/matplotlib/matplotlib/issues/3706#issuecomment-378407795
leg = ax.legend(**kwargs)
if ax_placein is not None:
leg.remove()
ax_placein.add_artist(leg)
return leg
所以,有了这个功能,你就可以简单地做
legend = legend_to_ax( ax, ax_placein=ax2, method=1, facecolor="white")
或
legend = legend_to_ax( ax, ax_placein=ax2, method=2, facecolor="white")
如果您确实想要两个图例,这应该可行:
legend1 = legend_to_ax( ax, ax_placein=ax2, method=2, facecolor="white", loc="upper left")
legend2 = legend_to_ax( ax2, ax_placein=ax2, method=2, facecolor="white", loc="upper right")
我希望这是一个分享这些信息的合适场所。不过,归功于@ImportanceOfBeingErnest。我只是将他们的解决方案合并到这个函数中。