matplotlib 中置信区间和值的水平图

horizontal plot of confidence interval and values in matplotlib

我正在使用 matplotlib Python,我希望能够绘制与给定置信区间相比的值,以便于阅读。

假设我有数据:

labelstr = [ 'name1','name2','name3' ] 
values = [ 2.1, 40.5, 10.9 ]
lower_bound =  [ 1.8, 38.9 , 10.2 ]
upper_bound =  [ 2.3, 43.8 , 10.7 ]

我想绘制具有相应置信区间的值以显示该值是否属于。我正在寻找一种水平显示结果的方法。理想情况下,如果属于该点,则用一种颜色标记该点,如果不属于,则用不同的颜色标记。

我还想要显示图中点的值以及上下限。

本例中的内容会很方便https://blog.uvm.edu/tbplante/2018/03/14/code-to-make-a-dot-and-95-confidence-interval-figure-in-stata/

有什么建议吗?谢谢

因为你已经有了聚合值和边界,使用 Axes.errorbar 接受 xerr 水平错误:

shape(2, N): Separate lower and upper values for each bar. First row contains the lower errors, the second row contains the upper errors.
Note that all error arrays should have positive values.

  1. 将边界转换为形状 2xN 的相对误差:

    xerr = [
        [value-lower for value, lower in zip(values, lower_bound)],
        [upper-value for value, upper in zip(values, upper_bound)],
    ]
    
    # [[0.30000000000000004, 1.6000000000000014, 0.7000000000000011],
    #  [0.19999999999999973, 3.299999999999997, -0.20000000000000107]]
    

    请注意,当文档说这些值应该为正时,它假定您的所有值都在范围内。在您的示例中,10.9 超出了 10.7 的上限,因此负值是预期的并且应该保持负值。

  2. 使用numpy.any and numpy.where(或列表理解)生成颜色数组(如果xerr为负则为橙色,否则为绿色):

    import numpy as np
    
    inbounds = np.any(np.array(xerr) < 0, axis=0)
    colors = np.where(inbounds, 'orange', 'green')
    
    # array(['green', 'green', 'orange'], dtype='<U8')
    
  3. 使用 Axes.scatter 绘制值,使用 Axes.errorbar 绘制错误,使用 [=20= 绘制标签]:

    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots()
    ax.scatter(values, labelstr, c=colors, s=30, marker='|')
    ax.set_ylim(-0.5, len(labelstr) - 0.5) # add some vertical padding
    ax.set_xticks([])
    
    ax.errorbar(values, labelstr, xerr=xerr,
        fmt='none',     # don't connect data points
        ecolor='black', # color of error lines
        elinewidth=1,   # width of error lines
        capsize=4,      # length of error caps
        zorder=-1,      # put error bars behind scatter points
    )
    
    for value, lower, upper, label, color in zip(values, lower_bound, upper_bound, labelstr, colors):
        shared = dict(xy=(value, label), color=color, textcoords='offset points', ha='center')
        ax.annotate(value, xytext=(0, 5), va='bottom', **shared)
        ax.annotate(f'[{lower}, {upper}]', xytext=(0, -5), va='top', **shared)