Розмір контейнера в 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 bins


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

У мене було те саме питання, що і в ОП (я думаю!), Але я не міг змусити його працювати так, як вказав Ластальда. Я не знаю, чи правильно я інтерпретував це питання, але я знайшов інше рішення (мабуть, це дуже поганий спосіб зробити це).

Це було так, як я це робив:

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

Що створює це:

зображення, що показує графік гістограми, створений у matplotlib

Отже, перший параметр в основному 'ініціалізує' бін - я спеціально створюю число, яке знаходиться між діапазоном, який я задаю в параметрі bins.

Щоб продемонструвати це, подивіться на масив у першому параметрі ([1,11,21,31,41]) та масив 'bins' у другому параметрі ([0,10,20,30,40,50]) :

  • Число 1 (з першого масиву) падає між 0 і 10 (у масиві 'bins')
  • Число 11 (з першого масиву) падає між 11 і 20 (у масиві 'bins')
  • Число 21 (від першого масиву) падає між 21 і 30 (у масиві 'bins') тощо.

Тоді я використовую параметр 'ваги', щоб визначити розмір кожного контейнера. Це масив, який використовується для параметра зважування: [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.