Создание pyplot.hist() первого и последнего бункеров включает выбросы
Документация
pyplot.hist()
указывает, что при установке диапазона для гистограммы "нижние и верхние выбросы игнорируются".
Можно ли сделать первый и последний бункеры гистограммы включать все выбросы без изменения ширины бункера?
Например, скажем, я хочу посмотреть на диапазон 0-3
с тремя ячейками: 0-1, 1-2, 2-3
(пусть простоту игнорируют случаи точного равенства). Я бы хотел, чтобы первый bin включал все значения от минус бесконечности до 1, а последний бит включал все значения от 2 до бесконечности. Однако, если я явно установил эти ячейки в этот диапазон, они будут очень широкими. Я бы хотел, чтобы они имели одинаковую ширину. Поведение, которое я ищу, похоже на поведение hist()
в Matlab.
Очевидно, я могу numpy.clip()
данные и график, которые дадут мне то, что я хочу. Но мне интересно, если для этого есть встроенное решение.
Ответы
Ответ 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.]()