[英]Matplotlib - legend picking on fill_between
我正在嘗試在 matplotlib 的 fill_between ( 鏈接到 fill_between 文檔)上使用圖例選擇( 鏈接到圖例選擇文檔)。
當我使用 matplotlib.pyplot.plot 時它工作得很好,但是當我在 matplotlib.pyplot.fill_between 上使用它時沒有任何反應,但我沒有收到要修復的錯誤。 我懷疑我與填充命令不是線條有關,我使用 get_lines() 函數,但我很難真正理解正在發生的事情。
使用 plt.plot 輸出“工作線”上的額外逗號是由於 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()
找到了解決方案。
代替 leg.get_lines() 使用 leg.findobj ,我在 findobj 函數中使用“match”參數搜索 patch.Rectangles 。 請記住“從 matplotlib 導入補丁”導入庫。
出於某種原因,在 python 3.9 中,當單擊圖例並禁用繪圖並更改圖例矩形的不透明度時,矩形的顏色變為默認藍色(不知道為什么?!)。 為了解決這個問題,我必須從 fill_between 圖中獲取顏色,並在 on_pick 函數中設置圖例矩形的顏色。 編輯:如果我更改為另一個 python exe(仍然是 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]
# fill_plot_color = fill_plot.get_facecolor() # set if all blue plots
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_color) # set if all blue plots
fig.canvas.draw()
fig.canvas.mpl_connect('pick_event', on_pick)
plt.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.