【问题标题】:How to annotate error values on matplotlib bar plot如何在 matplotlib 条形图上注释错误值
【发布时间】:2020-10-24 11:38:15
【问题描述】:

我有以下问题:

我想用条形高度(y 值)和误差线高度(误差值)来注释我的条形图 - 具有标准误差线

我找到了注释条形图的链接Annotate bars with values on Pandas bar plots。建议的策略迭代 Axes Patches 并获取补丁高度以检索 y 值,但我没有找到任何可以提取错误值的东西。

我想得到以下结果:

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    在下面,考虑到不对称 yerror,我已经修改了 bar_label 以执行与您所要求的类似的操作。

    编辑代码末尾的'%d[%d,%d]' % (value,err[0,1],err[1,1]),以您想要的任何格式显示错误。即,使用'%.2f$\pm$%.2f' % (value,err[0,1]) 来显示对称错误。通过调整 err 矩阵索引,也可以轻松考虑 xerrors。

    import itertools
    def bar_label(container, labels=None, *, fmt="%g", label_type="edge",
                  padding=0, **kwargs):
    
        # want to know whether to put label on positive or negative direction
        # cannot use np.sign here because it will return 0 if x == 0
        def sign(x):
            return 1 if x >= 0 else -1
    
        bars = container.patches
        errorbar = container.errorbar
        datavalues = container.datavalues
        orientation = container.orientation
    
        if errorbar:
            # check "ErrorbarContainer" for the definition of these elements
            lines = errorbar.lines  # attribute of "ErrorbarContainer" (tuple)
            barlinecols = lines[2]  # 0: data_line, 1: caplines, 2: barlinecols
            barlinecol = barlinecols[0]  # the "LineCollection" of error bars
            errs = barlinecol.get_segments()
        else:
            errs = []
    
        if labels is None:
            labels = []
    
        annotations = []
    
        for bar, err, dat, lbl in itertools.zip_longest(
            bars, errs, datavalues, labels
        ):
            (x0, y0), (x1, y1) = bar.get_bbox().get_points()
            xc, yc = (x0 + x1) / 2, (y0 + y1) / 2
    
            if orientation == "vertical":
                extrema = max(y0, y1) if dat >= 0 else min(y0, y1)
                length = abs(y0 - y1)
            elif orientation == "horizontal":
                extrema = max(x0, x1) if dat >= 0 else min(x0, x1)
                length = abs(x0 - x1)
    
            if err is None:
                endpt = extrema
            elif orientation == "vertical":
                endpt = err[:, 1].max() if dat >= 0 else err[:, 1].min()
            elif orientation == "horizontal":
                endpt = err[:, 0].max() if dat >= 0 else err[:, 0].min()
    
            if label_type == "center":
                value = sign(dat) * length
            elif label_type == "edge":
                value = extrema
    
            if label_type == "center":
                xy = xc, yc
            elif label_type == "edge" and orientation == "vertical":
                xy = xc, endpt
            elif label_type == "edge" and orientation == "horizontal":
                xy = endpt, yc
    
            if orientation == "vertical":
                xytext = 0, sign(dat) * padding
            else:
                xytext = sign(dat) * padding, 0
    
            if label_type == "center":
                ha, va = "center", "center"
            elif label_type == "edge":
                if orientation == "vertical":
                    ha = 'center'
                    va = 'top' if dat < 0 else 'bottom'  # also handles NaN
                elif orientation == "horizontal":
                    ha = 'right' if dat < 0 else 'left'  # also handles NaN
                    va = 'center'
    
            if np.isnan(dat):
                lbl = ''
    
            annotation = plt.annotate('%d[%d,%d]' % (value,err[0,1],err[1,1]), #fmt % value if lbl is None else lbl,
                                      xy, xytext, textcoords="offset points",
                                      ha=ha, va=va, **kwargs)
            annotations.append(annotation)
    
        return annotations
    

    【讨论】:

      猜你喜欢
      • 2018-08-02
      • 2014-10-16
      • 2017-01-23
      相关资源
      最近更新 更多