Подтвердить что ты не робот

Создание pyplot.hist() первого и последнего бункеров включает выбросы

Документация

pyplot.hist() указывает, что при установке диапазона для гистограммы "нижние и верхние выбросы игнорируются".

Можно ли сделать первый и последний бункеры гистограммы включать все выбросы без изменения ширины бункера?

Например, скажем, я хочу посмотреть на диапазон 0-3 с тремя ячейками: 0-1, 1-2, 2-3 (пусть простоту игнорируют случаи точного равенства). Я бы хотел, чтобы первый bin включал все значения от минус бесконечности до 1, а последний бит включал все значения от 2 до бесконечности. Однако, если я явно установил эти ячейки в этот диапазон, они будут очень широкими. Я бы хотел, чтобы они имели одинаковую ширину. Поведение, которое я ищу, похоже на поведение hist() в Matlab.

Очевидно, я могу numpy.clip() данные и график, которые дадут мне то, что я хочу. Но мне интересно, если для этого есть встроенное решение.

4b9b3361

Ответ 1

Нет. Глядя на matplotlib.axes.Axes.hist и прямое использование numpy.histogram, я довольно уверен в том, что нет более разумного решения, чем использование клипа (кроме расширения бункеров, которые вы используете с гистограммой).

Я бы посоветовал вам посмотреть на источник matplotlib.axes.Axes.hist (это просто код Python, хотя, по общему признанию, гид немного сложнее большинства методов Axes) - это лучший чтобы проверить этот вопрос.

НТН

Ответ 2

Я также боролся с этим и не хотел использовать .clip() потому что это может вводить в заблуждение, поэтому я написал небольшую функцию (заимствуя из этого много), чтобы указать, что верхний и нижний столбцы содержат выбросы:

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()

Вы также можете комбинировать его с автоматическим детектором выбросов (заимствованным здесь) следующим образом:

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.