【问题标题】:Making pyplot.hist() first and last bins include outliers使 pyplot.hist() 第一个和最后一个 bin 包含异常值
【发布时间】:2013-03-28 02:20:39
【问题描述】:

pyplot.hist() 文档指定在为直方图设置范围时“忽略上下异常值”

是否可以让直方图的第一个和最后一个 bin 包含所有异常值而不改变 bin 的宽度

例如,假设我想查看具有 3 个 bin 的范围 0-30-1, 1-2, 2-3(为简单起见,我们忽略完全相等的情况)。我希望第一个 bin 包含从负无穷到 1 的所有值,最后一个 bin 包含从 2 到无穷大的所有值。但是,如果我明确地将这些箱设置为跨越该范围,它们将非常宽。我希望它们具有相同的宽度。我正在寻找的行为类似于 Matlab 中 hist() 的行为。

显然我可以numpy.clip() 数据并绘制它,这将给我我想要的。但是我很感兴趣,如果有一个内置的解决方案。

【问题讨论】:

  • 听起来您有一个两行解决方案 (numpy.clip(); pyplot.hist()),并且您想要一个单行解决方案。虽然我猜hist()clip 关键字会很好,但我认为没有人会费心去实现它,因为它太基础了。当然,您可以随时向 matplotlib 提交补丁 :-)。
  • 是的,@Evert 是对的,clip 是最好的解决方案。我想说pyplot.hist() 没有建立这个可能是因为如果不仔细注释它会产生误导性的情节。
  • @Evert 好的,谢谢。我只是想看看我没有错过一些更好的解决方案来获得这种行为。

标签: python numpy matplotlib


【解决方案1】:

我也在为此苦苦挣扎,不想使用.clip(),因为它可能会产生误导,所以我写了一个小函数(大量借用this)来表明上下垃圾箱包含异常值:

def outlier_aware_hist(data, lower=None, upper=None):
    if not lower or lower < data.min():
        lower = data.min()
        lower_outliers = False
    else:
        lower_outliers = True

    if not upper or upper > data.max():
        upper = data.max()
        upper_outliers = False
    else:
        upper_outliers = True

    n, bins, patches = plt.hist(data, range=(lower, upper), bins='auto')

    if lower_outliers:
        n_lower_outliers = (data < lower).sum()
        patches[0].set_height(patches[0].get_height() + n_lower_outliers)
        patches[0].set_facecolor('c')
        patches[0].set_label('Lower outliers: ({:.2f}, {:.2f})'.format(data.min(), lower))

    if upper_outliers:
        n_upper_outliers = (data > upper).sum()
        patches[-1].set_height(patches[-1].get_height() + n_upper_outliers)
        patches[-1].set_facecolor('m')
        patches[-1].set_label('Upper outliers: ({:.2f}, {:.2f})'.format(upper, data.max()))

    if lower_outliers or upper_outliers:
        plt.legend()

您还可以将其与自动异常值检测器(借用自 here)结合起来,如下所示:

def mad(data):
    median = np.median(data)
    diff = np.abs(data - median)
    mad = np.median(diff)
    return mad

def calculate_bounds(data, z_thresh=3.5):
    MAD = mad(data)
    median = np.median(data)
    const = z_thresh * MAD / 0.6745
    return (median - const, median + const)

outlier_aware_hist(data, *calculate_bounds(data))

【讨论】:

  • 很好,我偷了它。但是,我认为您在使用它时必须注意直方图的第一个和最后一个 bin 包含异常值。它不是异常值的单独罐
【解决方案2】:

没有。看看matplotlib.axes.Axes.histnumpy.histogram 的直接使用,我很有信心说没有比使用剪辑更聪明的解决方案(除了扩展直方图所用的箱)。

我建议您查看 matplotlib.axes.Axes.hist 的源代码(它只是 Python 代码,尽管公认 hist 比大多数 Axes 方法稍微复杂一些) - 这是 最好的方法来验证这类问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多