首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Matplotlib -在fill_between上选择图例

Matplotlib -在fill_between上选择图例
EN

Stack Overflow用户
提问于 2022-07-13 08:32:47
回答 1查看 163关注 0票数 0

我试图在matplotlib的链接到图例拾取涂鸦( fill_between,在涂鸦)上使用图例拾取( legend )。

当我使用matplotlib.pyplot.plot时,它可以很好地工作,但是当我在matplotlib.pyplot.fill_between上使用它时,什么都不会发生,但是我没有收到要修复的错误。我怀疑我与填充命令(而不是行)有关,我使用了get_lines()函数,但我很难真正理解正在发生的事情。

在输出“工作线”上使用plt.plot的额外逗号是由于绘图返回一个元组,而fill_between返回一个值。

代码语言:javascript
运行
复制
    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()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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)“也不是必需的。

以上代码的解决方案:

代码语言:javascript
运行
复制
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()

一个更笼统的答案是:

代码语言:javascript
运行
复制
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()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72963172

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档