使用辅助轴时,图例透明度

bzn*_*bzn 6 python matplotlib

副轴图的图例以某种方式对另一轴的图是透明的.重现问题的最小示例:

import matplotlib.pyplot as plt

ax1 = plt.subplot(111)
ax2 = ax1.twinx()
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r')  
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')
ax1.legend(loc=2)
plt.show()
Run Code Online (Sandbox Code Playgroud)

我得到的输出是: 错误的情节

如您所见,蓝色图的图例被红色图透支.重新排列绘图命令,更改alpha值或更改对象的z顺序没有帮助.

有没有办法让传说对所有情节都不透明?

编辑:@ tcaswell:虽然您的答案适用于单个图例,但如果两个轴都有单独的图例,则它不起作用.在以下代码中,我添加了一个标签ax2:

import matplotlib.pyplot as plt
plt.figure()
ax1 = plt.subplot(111)
ax2 = ax1.twinx()
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r', label='ax2')  
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')
ax1.legend(loc=2)
ax2.legend(loc=1)

ax1.set_zorder(1) # make it on top
ax1.set_frame_on(False) # make it transparent
ax2.set_frame_on(True) # make sure there is any background

plt.show()
Run Code Online (Sandbox Code Playgroud)

结果如下:

错误的情节有两个传说

虽然您更通用的方法可以解决这个问题,但Figure.legend遗憾的是,使用图例将其放在图表之外.明确地放置它们loc有点单调乏味,并且在缩放绘图时效果不佳.有更好的解决方案吗?

tac*_*ell 8

由于matplotlib渲染图的方式,您遇到了问题.默认情况下,第二个轴在第一个轴之后渲染(它们具有相同的轴,zorder因此它们按照添加的顺序渲染).

要得到你想要的东西你只需要调整一些关于你的轴的东西:

figure()
ax1 = plt.subplot(111)
ax2 = ax1.twinx()
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r')  
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')
ax1.legend(loc=2)

ax1.set_zorder(1) # make it on top
ax1.set_frame_on(False) # make it transparent
ax2.set_frame_on(True) # make sure there is any background

plt.show()
Run Code Online (Sandbox Code Playgroud)

我们设置zorderax1要高,因此稍后呈现,但如果我们做到这一点,作为框架(白色背景和框)下的所有绘制的第二轴是不可见的,就好象它ax1.为了解决这个问题,我们关闭了框架ax1(我们可以看到ax2).但是,现在我们根本没有背景或边界框.然后我们可以重新打开框架ax2,这会给我们带来理想的效果.

上面的方法是临时的而不是一般的,如果你想确保轴在所有轴之上,你需要使用Figure.ledgend(),这是一个figureaxes特征.目前,它不会自动神奇地找到您的标签,因此您必须明确传入句柄和标签:

fig = figure()

ax1 = plt.subplot(111)
ax2 = ax1.twinx()

ln2, = ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r', label='ax2')  
ln1, = ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')

interesting_lines = [ln1, ln2]

fig.legend(*zip(*[(il, il.get_label()) for il in interesting_lines]), loc=2)

plt.show()
Run Code Online (Sandbox Code Playgroud)

请注意,此图例现在使用图形坐标放置.