【问题标题】:Relative size of error bar cap size误差条上限大小的相对大小
【发布时间】:2018-02-08 22:33:54
【问题描述】:

是否可以动态控制误差线上限的大小?就像控制箱线图中的胡须帽一样?因此,无需将倾覆设置为某个固定值。从下面的例子中应该会看到更多。

fig = plt.figure()
gs = gridspec.GridSpec(2, 2)
ax0 = fig.add_subplot(gs[0])
ax1 = fig.add_subplot(gs[1])
ax2 = fig.add_subplot(gs[2])
ax3 = fig.add_subplot(gs[3])

n = 3
ax0.bar(list(range(n)),
       np.random.randint(1,20,n),
       yerr=np.random.randn(n),
       edgecolor="red",
       fill=False,
       capsize=5)

ax1.boxplot(np.random.normal(70, 25, (200,n)))

n = 12
ax2.bar(list(range(n)),
       np.random.randint(1,20,n),
       yerr=np.random.randn(n),
       edgecolor="red",
       fill=False,
       capsize= 5)

ax3.boxplot(np.random.normal(70, 25, (200,n)))


更多的话:

是否有可能以某种方式控制相对于垃圾箱之间的间距的倾覆。如果垃圾箱在所有整数上,我希望倾覆的宽度为bin_center +/- 0.25

【问题讨论】:

  • 恐怕不太清楚你想做什么。您能否再用几句话来解释您展示的图片有什么问题以及您希望它们看起来有何不同?
  • 希望更新澄清了这个问题。
  • 所做的编辑更加模糊。 0.25 不是一个相对数字。

标签: python-3.x matplotlib


【解决方案1】:

条形图上的误差线上限和箱线图上的须线上限之间存在巨大差异。胡须帽是图中的实际线条(即它们有起点和终点)。误差线的上限是标记;与您在通常的情节中使用marker="_" 获得的标记相同。

因此,晶须的宽度是线的两个坐标之间的差,而误差条帽的宽度是markersizemarkersize 以点为单位,使其独立于图中的数据单元。这有几个优点:它们在屏幕上保持大小,独立于数据比例,在缩放绘图时保持不变,并且在对数比例上看起来不错。

因此,当要求在数据单元中设置误差条上限大小时,您实际上是在询问如何在数据单元中缩放标记。例如,可以查看this questionthis one,它们要求缩放数据单元中的散点。

因此我们的想法是计算一个数据单元在当前图中有多少个点,然后将误差条上限的标记大小设置为该数字的倍数。

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)

fig, (ax,ax2) = plt.subplots(ncols=2, figsize=(8,4))

n = 3
bar1 = ax.bar(list(range(n)),
       np.random.randint(1,20,n),
       yerr=np.random.randn(n),
       edgecolor="red", fill=False, capsize=1)

n = 12
bar2 = ax2.bar(list(range(n)),
       np.random.randint(1,20,n),
       yerr=np.random.randn(n),
       edgecolor="red", fill=False, capsize=1)

class BarCapSizer():
    def __init__(self, caps, size=1):
        self.size=size
        self.caps = caps
        self.ax = self.caps[0].axes
        self.resize()

    def resize(self):
        ppd=72./self.ax.figure.dpi
        trans = self.ax.transData.transform
        s =  ((trans((self.size,1))-trans((0,0)))*ppd)[0]
        for i,cap in enumerate(self.caps):
            cap.set_markersize(s)

size = 0.5 # data units
bcs1 =  BarCapSizer(bar1.errorbar.lines[1], size )        
bcs2 =  BarCapSizer(bar2.errorbar.lines[1], size )

plt.show()

这显示了具有 0.5 个数据单元的翻船。现在的问题是,这又被修复了。因此,如果交互式缩放应该保留数据单元中的标记比例,则需要使用事件处理机制来更新标记大小。这可以类似于here 显示的那样完成。

class BarCapSizer():
    def __init__(self, caps, size=1):
        self.size=size
        self.caps = caps
        self.ax = self.caps[0].axes
        self.resize()
        self.cid = ax.figure.canvas.mpl_connect('draw_event', self.update)

    def resize(self):
        ppd=72./self.ax.figure.dpi
        trans = self.ax.transData.transform
        s =  ((trans((self.size,1))-trans((0,0)))*ppd)[0]
        for i,cap in enumerate(self.caps):
            cap.set_markersize(s)

    def update(self,event=None):
        self.resize()
        self.timer = self.ax.figure.canvas.new_timer(interval=10)
        self.timer.single_shot = True
        self.timer.add_callback(lambda : self.ax.figure.canvas.draw_idle())
        self.timer.start()

【讨论】:

    【解决方案2】:

    如果我理解正确,您希望误差上限的大小自动调整到条形的宽度,就像它们在箱线图中所做的那样?

    在这种情况下,获得所需行为的一种简单方法是将一个值传递给capsize=,该值与条形的数量成反比,因为条形的数量最终将决定它们的宽度。您必须使用确切的比例系数,直到您对结果满意为止。

    fig, axs = plt.subplots(1,2, figsize=(5,2.5))
    
    for ax,n in zip(axs,[3,12]):
        ax.bar(list(range(n)),
           np.random.randint(1,20,n),
           yerr=np.random.randn(n),
           edgecolor="red",
           fill=False,
           capsize=30/n)  # <--- capsize inversly proportional to n
    

    【讨论】:

    • 如果这是唯一的解决方案,我会接受答案。但是对于条形图,这可以像箱形图中的胡须一样实现。谢谢。
    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    相关资源
    最近更新 更多