Matplotlib的set_data用于误差条图的绘制。

6

Matplotlib的line2D对象,例如通过调用plot返回的那些对象,具有一个方便的方法set_data,它让我可以快速更新单条线的绘制值,而不会影响到整个图或者该线的格式。

#sample plot
from matplotlib.pyplot import plot
p = plot(arange(10),arange(10))[0]

#now update the data
p.set_data(arange(10),arange(10)+2)
draw()

有没有相对简单(只需几行代码)的方法来完成errorbar图的同样效果?我想设置一个复杂的图表,包括各种文本、箭头、线条等,然后快速地将图表中的误差线部分循环显示不同的数据。

errorbar返回的对象似乎非常复杂,迄今为止,我的删除和重绘尝试都失败了。


很遗憾,我认为没有简单的方法可以做到这一点。您可以通过ErrorbarContainer对象的.lines属性访问构成图形的行,该属性会提供一个元组(xyline, caplines, errorbarlines)。调用xyline.set_data()足够简单。尴尬的是,您需要手动计算每个caplines的新xy位置。对于errorbarlines,您也需要做同样的事情,由于它们是LineCollection的元组,因此需要向.set_segments()方法传递一个序列(x0,y0),(x1,y1),...,(xm,ym) - ali_m
你可以考虑在 numpy Github 仓库 上提交一个功能请求。 - ali_m
功能请求已经提交!不过我是在matplotlib的Github存储库上提交的,而不是numpy。 https://github.com/matplotlib/matplotlib/issues/3366 - parkus
哦,是的,那样更有意义... - ali_m
根据我收到的matplotlib功能请求的回复,这个功能将在1.5.x版本中实现。 - parkus
是的,我看到了 - MEP25 中提出的更广泛的变化看起来很棒。 - ali_m
2个回答

4

感谢@tacaswell的帮助。 下面是一个Python函数,可以更新xerryerr,以及基线绘图的x_datay_data

def adjustErrbarxy(self, errobj, x, y, x_error, y_error):
    ln, (errx_top, errx_bot, erry_top, erry_bot), (barsx, barsy) = errobj
    x_base = x
    y_base = y

    xerr_top = x_base + x_error
    xerr_bot = x_base - x_error
    yerr_top = y_base + y_error
    yerr_bot = y_base - y_error

    errx_top.set_xdata(xerr_top)
    errx_bot.set_xdata(xerr_bot)
    errx_top.set_ydata(y_base)
    errx_bot.set_ydata(y_base)

    erry_top.set_xdata(x_base)
    erry_bot.set_xdata(x_base)
    erry_top.set_ydata(yerr_top)
    erry_bot.set_ydata(yerr_bot)

    new_segments_x = [np.array([[xt, y], [xb,y]]) for xt, xb, y in zip(xerr_top, xerr_bot, y_base)]
    new_segments_y = [np.array([[x, yt], [x,yb]]) for x, yt, yb in zip(x_base, yerr_top, yerr_bot)]
    barsx.set_segments(new_segments_x)
    barsy.set_segments(new_segments_y)

第一个输入参数(self是Python类)是已创建的errorbar绘图处理程序,也是需要更新属性的对象;xy是更新的numpy数组,应显示沿xy轴的平均值;最后两个参数x_errory_error是计算出的xy数组的errorbar范围。如果只需要更新误差条,则应将x_basey_base编写为ln.get_xdata()ln.get_ydata(),分别。

到目前为止,matplotliberrorbar更新的解决方案确实非常复杂,希望在未来版本中变得更加简单。


1
我跟随 Tong 提供的链接学习了一下,发现他的代码存在问题 - 不需要输入self变量。同时,mitpre 提供了一个更通用的解决方案 - 我使用它效果很好。以下是代码以便快速参考:
def update_errorbar(errobj, x, y, xerr=None, yerr=None):
    ln, caps, bars = errobj


    if len(bars) == 2:
        assert xerr is not None and yerr is not None, "Your errorbar object has 2 dimension of error bars defined. You must provide xerr and yerr."
        barsx, barsy = bars  # bars always exist (?)
        try:  # caps are optional
            errx_top, errx_bot, erry_top, erry_bot = caps
        except ValueError:  # in case there is no caps
            pass

    elif len(bars) == 1:
        assert (xerr is     None and yerr is not None) or\
               (xerr is not None and yerr is     None),  \
               "Your errorbar object has 1 dimension of error bars defined. You must provide xerr or yerr."

        if xerr is not None:
            barsx, = bars  # bars always exist (?)
            try:
                errx_top, errx_bot = caps
            except ValueError:  # in case there is no caps
                pass
        else:
            barsy, = bars  # bars always exist (?)
            try:
                erry_top, erry_bot = caps
            except ValueError:  # in case there is no caps
                pass

    ln.set_data(x,y)

    try:
        errx_top.set_xdata(x + xerr)
        errx_bot.set_xdata(x - xerr)
        errx_top.set_ydata(y)
        errx_bot.set_ydata(y)
    except NameError:
        pass
    try:
        barsx.set_segments([np.array([[xt, y], [xb, y]]) for xt, xb, y in zip(x + xerr, x - xerr, y)])
    except NameError:
        pass

    try:
        erry_top.set_xdata(x)
        erry_bot.set_xdata(x)
        erry_top.set_ydata(y + yerr)
        erry_bot.set_ydata(y - yerr)
    except NameError:
        pass
    try:
        barsy.set_segments([np.array([[x, yt], [x, yb]]) for x, yt, yb in zip(x, y + yerr, y - yerr)])
    except NameError:
        pass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接