我试图在matplotlib的链接到图例拾取涂鸦( fill_between,在涂鸦)上使用图例拾取( legend )。
当我使用matplotlib.pyplot.plot时,它可以很好地工作,但是当我在matplotlib.pyplot.fill_between上使用它时,什么都不会发生,但是我没有收到要修复的错误。我怀疑我与填充命令(而不是行)有关,我使用了get_lines()函数,但我很难真正理解正在发生的事情。
在输出“工作线”上使用plt.plot的额外逗号是由于绘图返回一个元组,而fill_between返回一个值。
df = pd.DataFrame(...)
x_dist = df['distance']
df.pop('distance')
labels = []
lines = []
fig, ax = plt.subplots()
cols = df.columns
for i, col in enumerate(cols):
bot = df[cols[i]] # layer bot as bot
top = df[cols[i - 1]] # previous layer bot as top
# plot layer if the layer has different values from the layers above
if col[:4] != '0000': # discard terrain (first entry)
if not bot.equals(top):
pl = ax.fill_between(x_dist, top, bot, label=col) # non-working line
# pl, = ax.plot(x_dist, bot, label=col) # working line
lines.append(pl)
labels.append(pl.get_label())
# set grid on plot
ax.grid('both')
# set legend on plot and place it outside plot
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
leg = ax.legend(fancybox=True, shadow=True, loc='center left', bbox_to_anchor=(1, 0.5))
lined = {} # Will map legend lines to original lines.
for legline, origline in zip(leg.get_lines(), lines):
legline.set_picker(True) # Enable picking on the legend line.
lined[legline] = origline
def on_pick(event):
legline = event.artist
origline = lined[legline]
visible = not origline.get_visible()
origline.set_visible(visible)
legline.set_alpha(1.0 if visible else 0.2)
fig.canvas.draw()
fig.canvas.mpl_connect('pick_event', on_pick)
plt.show()
发布于 2022-07-14 07:20:19
找到了解决办法。
这里使用的不是leg.get_lines(),而是leg.findobj,在这里,我使用findobj函数中的"match“参数搜索patches.Rectangles。记住“从matplotlib导入修补程序”导入库。
由于某些原因,在python 3.9中,当单击图例并禁用绘图并更改图例矩形的不透明度时,矩形的颜色将更改为默认的蓝色(不知道为什么?!)。要解决这个问题,我必须从fill_between图中获取颜色,并在on_pick函数中设置图例矩形的颜色。编辑:如果我更改为另一个python (仍然是3.9版),这个错误就不会发生,并且"leg_obj.set_color(fill_plot_color)“也不是必需的。
以上代码的解决方案:
df = pd.DataFrame(...)
x_dist = df['distance']
df.pop('distance')
labels = []
lines = []
fig, ax = plt.subplots()
cols = df.columns
for i, col in enumerate(cols):
bot = df[cols[i]] # layer bot as bot
top = df[cols[i - 1]] # previous layer bot as top
# plot layer if the layer has different values from the layers above
if col[:4] != '0000': # discard terrain (first entry)
if not bot.equals(top):
pl = ax.fill_between(x_dist, top, bot, label=col) # non-working line
# pl, = ax.plot(x_dist, bot, label=col) # working line
lines.append(pl)
labels.append(pl.get_label())
# set grid on plot
ax.grid('both')
# set legend on plot and place it outside plot
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
leg = ax.legend(fancybox=True, shadow=True, loc='center left', bbox_to_anchor=(1, 0.5))
lined = {} # Will map legend lines to original lines.
for legline, origline in zip(leg.findobj(patches.Rectangle), lines):
legline.set_picker(True) # Enable picking on the legend line.
lined[legline] = origline
def on_pick(event):
legline = event.artist
origline = lined[legline]
color_fill = origline.get_facecolor()
visible = not origline.get_visible()
origline.set_visible(visible)
legline.set_alpha(1.0 if visible else 0.2)
legline.set_color(color_fill)
fig.canvas.draw()
fig.canvas.mpl_connect('pick_event', on_pick)
plt.show()
一个更笼统的答案是:
from matplotlib import pyplot as plt, patches
import numpy as np
x = np.linspace(1, 10, 10)
y1 = np.linspace(1, 5, 10)
y2 = np.linspace(10, 20, 10)
fig, ax = plt.subplots()
pl = ax.fill_between(x, y1, y2, label='fill_plot')
leg = ax.legend()
fill_plots = [pl]
leg_to_fill = {}
for leg_obj, fill_plot in zip(leg.findobj(patches.Rectangle), fill_plots):
leg_obj.set_picker(True)
leg_to_fill[leg_obj] = fill_plot
def on_pick(event):
leg_obj = event.artist
fill_plot = leg_to_fill[leg_obj]
visible = not fill_plot.get_visible()
fill_plot.set_visible(visible)
leg_obj.set_alpha(1.0 if visible else 0.2)
# leg_obj.set_color(fill_plot.get_facecolor()) # set if all blue plots
fig.canvas.draw()
fig.canvas.mpl_connect('pick_event', on_pick)
plt.show()
https://stackoverflow.com/questions/72963172
复制相似问题