【发布时间】:2020-10-24 11:38:15
【问题描述】:
我有以下问题:
我想用条形高度(y 值)和误差线高度(误差值)来注释我的条形图 - 具有标准误差线。
我找到了注释条形图的链接Annotate bars with values on Pandas bar plots。建议的策略迭代 Axes Patches 并获取补丁高度以检索 y 值,但我没有找到任何可以提取错误值的东西。
我想得到以下结果:
【问题讨论】:
标签: python matplotlib
我有以下问题:
我想用条形高度(y 值)和误差线高度(误差值)来注释我的条形图 - 具有标准误差线。
我找到了注释条形图的链接Annotate bars with values on Pandas bar plots。建议的策略迭代 Axes Patches 并获取补丁高度以检索 y 值,但我没有找到任何可以提取错误值的东西。
我想得到以下结果:
【问题讨论】:
标签: python matplotlib
在下面,考虑到不对称 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
【讨论】: