制作pyplot.hist()的第一个和最后一个包含异常值

时间:2013-04-05 15:29:48

标签: python numpy matplotlib

pyplot.hist()文档指定在设置直方图的范围时,“忽略较低和较高的异常值”

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

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

显然我可以numpy.clip()数据和情节,这将给我我想要的东西。但我感兴趣的是,如果有一个内置的解决方案。

2 个答案:

答案 0 :(得分:8)

没有。看matplotlib.axes.Axes.hist并直接使用numpy.histogram我相当自信地说没有比使用剪辑更聪明的解决方案(除了扩展直方图所用的箱子)。

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

HTH

答案 1 :(得分:5)

我也在为此而苦苦挣扎,并且不想使用.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))

Generated data from a standard normal and then added some outliers. Plots with and without outlier binning.