Matplotlib: Как сделать гистограмму с ячейками равной площади?

Учитывая некоторый список чисел после некоторого произвольного распределения, как я могу определить позиции бина дляmatplotlib.pyplot.hist() так что площадь в каждой ячейке равна (или близка) к некоторой постоянной площади, A? Площадь должна быть рассчитана путем умножения количества элементов в корзине на ширину корзины, и ее значение не должно превышать A.

Вот MWE для отображения гистограммы с нормально распределенными образцами данных:

import matplotlib.pyplot as plt
import numpy as np

x = np.random.randn(100)
plt.hist(x, bin_pos)
plt.show()

Вотbin_pos список, представляющий позиции границ бункеров (см. связанный вопросВот.

 farenorth06 июн. 2016 г., 06:00
Я полагаю, вы будете указывать количество бинов в качестве ввода?
 armatita06 июн. 2016 г., 22:04
Дело в том, что площадь будет зависеть от ширины и высоты. Высота определяется количеством элементов внутри корзины, а ширина будет определять интервал для этих элементов. Так что, если вы хотите изменить область, числа на оси X также будут изменены (оставив нормальное декартово пространство). Это то, что вы хотите? Нелинейная ось X? Или я это неправильно интерпретирую ...?
 wrkyle06 июн. 2016 г., 06:09
Хм, это хороший момент. Полагаю, мне нужно это указать. Так что, да, количество ячеек будет установлено.

Ответы на вопрос(1)

Решение Вопроса

хотите ли вы построитьфункция плотностиилиистинная гистограмма, Последний случай оказывается немного более сложным.Вот больше информации о разнице между гистограммой и функцией плотности.

Функции плотности

Это будет делать то, что вы хотите для функции плотности:

def histedges_equalN(x, nbin):
    npt = len(x)
    return np.interp(np.linspace(0, npt, nbin + 1),
                     np.arange(npt),
                     np.sort(x))

x = np.random.randn(1000)
n, bins, patches = plt.hist(x, histedges_equalN(x, 10), normed=True)

Обратите внимание на использованиеnormed=True, который указывает, что мы рассчитываем и строим график функции плотности. В этом случае области одинаково равны (вы можете проверить, посмотрев наn * np.diff(bins)). Также обратите внимание, что это решение включает в себя поиск лотков с одинаковым количеством точек.

Гистограммы

Вот решение, которое дает примерно одинаковые области площади для гистограммы:

def histedges_equalA(x, nbin):
    pow = 0.5
    dx = np.diff(np.sort(x))
    tmp = np.cumsum(dx ** pow)
    tmp = np.pad(tmp, (1, 0), 'constant')
    return np.interp(np.linspace(0, tmp.max(), nbin + 1),
                     tmp,
                     np.sort(x))

n, bins, patches = plt.hist(x, histedges_equalA(x, nbin), normed=False)

Эти коробки, однако, не все равные области. Первый и последний, в частности, как правило, примерно на 30% больше, чем другие. Это является артефактом разреженного распределения данных в хвостах нормального распределения, и я полагаю, что оно сохранится в любое время, когда они являются малонаселенной областью в наборе данных.

Примечание: я играл со значениемpow немного, и обнаружил, что значение около0.56 был нижеRMS ошибка для нормального распределения. Я придерживался квадратного корня, потому что он работает лучше всего, когда данные тесно расположены (относительно ширины бина), и я почти уверен, что для этого есть теоретическая основа, в которую я не потрудился копаться ( кто-нибудь?).

Проблема с гистограммами равных площадей

Насколько я могу судить, невозможно получить точное решение этой проблемы. Это потому, что он чувствителен к дискретизации данных. Например, предположим, что первая точка в вашем наборе данных является выбросом в -13, а следующее значение в -3, как показано красными точками на этом изображении:

Теперь предположим, что общая «площадь» вашей гистограммы равна 150, и вы хотите 10 бинов. В этом случае площадь каждого столбца гистограммы должна быть около 15, но вы не можете попасть туда, потому что, как только ваш столбец включает в себя вторую точку, его площадь увеличивается с 10 до 20. То есть данные не позволяют этот столбец иметь область между 10 и 20. Одним из решений для этого может быть настройка нижней границы поля для увеличения его площади, но это начинает становиться произвольным и не работает, если этот «пробел» находится в середине поля. набор данных.

 wrkyle07 июн. 2016 г., 00:31
Вы - воплощение всего, что правильно с переполнением стека. Спасибо за ваше подробное, хорошо документированное и элегантное решение.
 farenorth07 июн. 2016 г., 01:29
Я просто хочу, чтобы SO был заполнен вопросами, которые были такими интересными. То есть, если бы это было так, я бы никогда больше ничего не сделал ...

Ваш ответ на вопрос