简体   繁体   English

用于误差条图的 Matplotlib set_data

[英]Matplotlib set_data for errorbar plot

Matplotlib's line2D objects, such as those returned by a call to plot , have a convenient method, set_data , that let's me quickly update the values plotted by a single line without affecting the rest of the plot or the formatting of the line. 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()

Is there any relatively simple (few lines of code) way to do the same with an errorbar plot?是否有任何相对简单的(几行代码)方法可以对errorbar图执行相同的errorbar I'd like to be able to set up a complicated plot with assorted text, arrows, lines, etc., then quickly cycle just the errorbar portion of the plot through several different sets of data.我希望能够使用各种文本、箭头、线条等设置复杂的绘图,然后通过几组不同的数据快速循环绘图的误差条部分。

The object returned by errorbar seems to be pretty complex and so far my attempts at deleting and redrawing have failed. errorbar返回的对象似乎非常复杂,到目前为止我尝试删除和重绘都失败了。

Thanks to the help from @tacaswell .感谢@tacaswell 的帮助 Below is the python function that can both update xerr and yerr , as well as the x_data and y_data for the baseline plotting:下面是可以更新xerryerr以及用于基线绘图的x_datay_data的python函数:

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)

The first input parameter ( self is for python class) is the already created errorbar plot handler, that is also the object whose properties need to be updated;第一个输入参数( self是python类的)是已经创建errorbar plot handler,也是需要更新属性的对象; x and y are the updated numpy arrays which should be shown the average values along x and y axis; xy是更新后的numpy数组,应显示沿xy轴的平均值; the last two parameters x_error and y_error are the errorbar ranges calculated for x and y arrays.最后两个参数x_errory_error是为xy数组计算的errorbar范围。 If only the errorbars are need to be updated, the x_base and y_base should be writen as ln.get_xdata() and ln.get_ydata() , respectively.如果只需要更新x_base ,则x_basey_base应分别写为ln.get_xdata()ln.get_ydata()

Up to now, the solution for the errorbar updating in matplotlib is truly non-trivial, hope it be much easier in the future versions.到目前为止, matplotlib errorbar更新的解决方案确实不平凡,希望在未来的版本中更容易。

I followed the link provided by Tong and learned that there is a problem in his code - input of self variable is not needed.我按照Tong提供的链接,得知他的代码有问题——不需要输入self变量。 There is also a more generalized solution provided by mitpre - I used it and it works great. mitpre还提供了一个更通用的解决方案 - 我使用过它并且效果很好。 Below is the code for quicker reference:以下是快速参考的代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM