Размер бина в Matplotlib (гистограмма)


149

Я использую matplotlib для создания гистограммы.

Есть ли способ вручную установить размер бункеров в отличие от количества бункеров?

Ответы:


270

На самом деле, это довольно просто: вместо количества бинов вы можете дать список с границами бинов. Они также могут быть неравномерно распределены:

plt.hist(data, bins=[0, 10, 20, 30, 40, 50, 100])

Если вы просто хотите, чтобы они были равномерно распределены, вы можете просто использовать диапазон:

plt.hist(data, bins=range(min(data), max(data) + binwidth, binwidth))

Добавлено в исходный ответ

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

import numpy as np
plt.hist(data, bins=np.arange(min(data), max(data) + binwidth, binwidth))

20
замените диапазон (...) на np.arange (...), чтобы он работал с плавающей точкой.
макрокосм

6
Какова здесь ширина бина? Вы уже установили это значение?
UserYmY

1
Я считаю , что binwidth в этом примере может быть найден: (data.max() - data.min()) / number_of_bins_you_want. Это + binwidthможно изменить, чтобы 1сделать этот пример более понятным.
Джарад

2
В дополнение к превосходному решению CodingCat, приведенному выше, для данных с плавающей точкой, если вы хотите, чтобы столбцы гистограммы центрировались вокруг целых x-тиков, вместо того, чтобы иметь границы столбцов на x-тиках, попробуйте следующую настройку: bins = np.arange (dmin - 0.5, dmax + 0.5 + binwidth, binwidth)
DaveW

3
опция lw = 5, color = "white"или аналогичные вставки белых пробелов между барами
PatrickT

13

Для N бинов ребра бинов задаются списком из N + 1 значений, где первые N задают ребра нижнего бина, а +1 - верхний край последнего бина.

Код:

from numpy import np; from pylab import *

bin_size = 0.1; min_edge = 0; max_edge = 2.5
N = (max_edge-min_edge)/bin_size; Nplus1 = N + 1
bin_list = np.linspace(min_edge, max_edge, Nplus1)

Обратите внимание, что linspace создает массив от min_edge до max_edge, разбитый на N + 1 значений или N бинов


1
Обратите внимание, что ячейки включают их нижнюю границу и исключают их верхнюю границу, за исключением N + 1 (последней) ячейки, которая включает обе границы.
lukewitmer

4

Я предполагаю, что самым простым способом было бы рассчитать минимум и максимум имеющихся у вас данных, а затем вычислить L = max - min. Затем вы делите Lна желаемую ширину ячейки (я полагаю, это то, что вы подразумеваете под размером ячейки) и используете потолок этого значения в качестве количества ячейек.


это именно то, что я имел в виду, спасибо. Было просто интересно, если есть более простой способ, но это, кажется, найти спасибо!
Сэм Кример

Используя круглые числа, я не получаю размер круглой корзины с таким подходом. Кто-нибудь испытал это?
Брэд Урани

3

Мне нравится, чтобы все происходило автоматически, и ящики попадали в «хорошие» значения. Следующее, кажется, работает довольно хорошо.

import numpy as np
import numpy.random as random
import matplotlib.pyplot as plt
def compute_histogram_bins(data, desired_bin_size):
    min_val = np.min(data)
    max_val = np.max(data)
    min_boundary = -1.0 * (min_val % desired_bin_size - min_val)
    max_boundary = max_val - max_val % desired_bin_size + desired_bin_size
    n_bins = int((max_boundary - min_boundary) / desired_bin_size) + 1
    bins = np.linspace(min_boundary, max_boundary, n_bins)
    return bins

if __name__ == '__main__':
    data = np.random.random_sample(100) * 123.34 - 67.23
    bins = compute_histogram_bins(data, 10.0)
    print(bins)
    plt.hist(data, bins=bins)
    plt.xlabel('Value')
    plt.ylabel('Counts')
    plt.title('Compute Bins Example')
    plt.grid(True)
    plt.show()

У результата есть контейнеры на хороших интервалах размера корзины.

[-70. -60. -50. -40. -30. -20. -10.   0.  10.  20.  30.  40.  50.  60.]

гистограмма вычисленных бинов


Именно то, что я искал! Однако в некоторых случаях n_bins округляется из-за точности с плавающей запятой. Например , для desired_bin_size=0.05, min_boundary=0.850, max_boundary=2.05расчет n_binsстановится , int(23.999999999999993)который приводит к 23 вместо 24 , и поэтому один бен слишком мало. У меня сработало округление до целочисленного преобразования:n_bins = int(round((max_boundary - min_boundary) / desired_bin_size, 0)) + 1
М.

3

Я использую квантили, чтобы сделать урны единообразными и приспособленными к образцу:

bins=df['Generosity'].quantile([0,.05,0.1,0.15,0.20,0.25,0.3,0.35,0.40,0.45,0.5,0.55,0.6,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1]).to_list()

plt.hist(df['Generosity'], bins=bins, normed=True, alpha=0.5, histtype='stepfilled', color='steelblue', edgecolor='none')

введите описание изображения здесь


1
Отличная идея. Вы можете заменить список квантилей на np.arange(0, 1.01, 0.5)или np.linspace(0, 1, 21). Там нет ребер, но я так понимаю, у блоков одинаковая площадь, но разная ширина по оси X?
Томаш Гандор

2

У меня была та же проблема, что и у OP (я думаю!), Но я не мог заставить ее работать так, как указано в Lastalda. Я не знаю, правильно ли я интерпретировал вопрос, но я нашел другое решение (хотя, вероятно, это действительно плохой способ сделать это).

Это был способ, которым я сделал это:

plt.hist([1,11,21,31,41], bins=[0,10,20,30,40,50], weights=[10,1,40,33,6]);

Который создает это:

изображение, показывающее график гистограммы, созданный в matplotlib

Таким образом, первый параметр в основном «инициализирует» корзину - я специально создаю число, которое находится между диапазоном, который я установил в параметре bin.

Чтобы продемонстрировать это, посмотрите на массив в первом параметре ([1,11,21,31,41]) и массив «bin» во втором параметре ([0,10,20,30,40,50]) :

  • Число 1 (из первого массива) находится в диапазоне от 0 до 10 (в массиве «bin»)
  • Число 11 (из первого массива) находится между 11 и 20 (в массиве «bin»)
  • Число 21 (из первого массива) находится между 21 и 30 (в массиве «bin») и т. Д.

Затем я использую параметр 'weights', чтобы определить размер каждой корзины. Это массив, используемый для параметра weights: [10,1,40,33,6].

Таким образом, ячейке от 0 до 10 задается значение 10, ячейке от 11 до 20 задается значение 1, ячейке от 21 до 30 задается значение 40 и т. Д.


3
Я думаю, у вас есть базовое недопонимание, как работает функция гистограммы. Это ожидает необработанные данные. Итак, в вашем примере ваш массив данных должен содержать 10 значений от 0 до 10, 1 значение от 10 до 20 и так далее. Затем функция выполняет суммирование и рисование. То, что вы делаете выше, это обходной путь, потому что у вас уже есть суммы (которые вы затем вставляете в график, неправильно используя опцию «весов»). Надеюсь, это прояснит ситуацию.
CodingCat

-1

Для гистограммы с целочисленными значениями x я использовал

plt.hist(data, np.arange(min(data)-0.5, max(data)+0.5))
plt.xticks(range(min(data), max(data)))

Смещение 0,5 центрирует ячейки по значениям оси X. plt.xticksВызов добавляет клещ для любого целого.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.