Гистограмма Matplotlib

107

Так что у меня небольшая проблема. У меня есть набор данных в scipy, который уже находится в формате гистограммы, поэтому у меня есть центр ящиков и количество событий на ячейку. Как я могу теперь построить график в виде гистограммы. Я пробовал просто делать

bins, n=hist()

но это не понравилось. Есть рекомендации?

сумасшедший
источник

Ответы:

239
import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
hist, bins = np.histogram(x, bins=50)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) / 2
plt.bar(center, hist, align='center', width=width)
plt.show()

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

Объектно-ориентированный интерфейс также прост:

fig, ax = plt.subplots()
ax.bar(center, hist, align='center', width=width)
fig.savefig("1.png")

Если вы используете настраиваемые (непостоянные) ячейки, вы можете передать вычисление ширины using np.diff, передать ширину ax.barи использовать ax.set_xticksдля обозначения краев ячейки:

import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
bins = [0, 40, 60, 75, 90, 110, 125, 140, 160, 200]
hist, bins = np.histogram(x, bins=bins)
width = np.diff(bins)
center = (bins[:-1] + bins[1:]) / 2

fig, ax = plt.subplots(figsize=(8,3))
ax.bar(center, hist, align='center', width=width)
ax.set_xticks(bins)
fig.savefig("/tmp/out.png")

plt.show()

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

Unutbu
источник
Есть ли способ перенести края бункера на ось абсцисс гистограммы?
CMCDragonkai
@CMCDragonkai: plt.bar«s widthпараметр может принять массив-подобный объект (вместо скаляра). Таким образом, вы можете использовать width = np.diff(bins)вместо width = 0.7 * (bins[1] - bins[0]).
unutbu
Но widthнастройка сама по себе устанавливает только ширину полосы, верно? Я говорю о метках оси x (то есть я хочу, чтобы фактические края бункера были метками на оси x). Это должно быть похоже на то, как plt.histработает.
CMCDragonkai
2
@CMCDragonkai: вы можете использовать ax.set_xticksдля установки xlabels. Я добавил пример выше, чтобы показать, что я имею в виду.
unutbu
22

Если вам не нужны бары, вы можете построить это так:

import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

bins, edges = np.histogram(x, 50, normed=1)
left,right = edges[:-1],edges[1:]
X = np.array([left,right]).T.flatten()
Y = np.array([bins,bins]).T.flatten()

plt.plot(X,Y)
plt.show()

гистограмма

Маттиас123
источник
6
Вы также можете использовать ax.step.
tacaswell
12

Я знаю, что это не отвечает на ваш вопрос, но я всегда оказываюсь на этой странице, когда ищу решение matplotlib для гистограмм, потому что простое решение histogram_demoбыло удалено со страницы галереи примеров matplotlib.

Вот решение, которое не нужно numpyимпортировать. Я импортирую numpy только для генерации данных xдля построения графика. Он полагается на функцию histвместо функции, barкак в ответе @unutbu.

import numpy as np
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

import matplotlib.pyplot as plt
plt.hist(x, bins=50)
plt.savefig('hist.png')

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

Также проверьте Matplotlib галереи и примеры Matplotlib .

tommy.carstensen
источник
«Вот решение, которое не требует numpy» - первая строка кода импортирует numpy :)
Мартин Р.
2
@Martin R. Это только для создания данных для построения графика. См. Строки 4-6. Никакого использования numpy.
tommy.carstensen
6

Если вы хотите использовать pandas:

pandas.DataFrame({'x':hist[1][1:],'y':hist[0]}).plot(x='x',kind='bar')
Майкл Малак
источник
27
Если вы собираетесь предложить использовать, pandasвам, вероятно, следует включить ссылку на их сайт и более подробный пример, объясняющий, что происходит.
tacaswell
0

Думаю, это может быть кому-то полезно.

Функция гистограммы Numpy, к моему раздражению (хотя, я понимаю, что для этого есть веская причина), возвращает обратно края каждого бина, а не его значение. Хотя это имеет смысл для чисел с плавающей запятой, которые могут находиться в пределах интервала (т. Е. Центральное значение не имеет особого смысла), это не желаемый результат при работе с дискретными значениями или целыми числами (0, 1, 2 и т. Д.) . В частности, длина бинов, возвращаемых из np.histogram, не равна длине отсчетов / плотности.

Чтобы обойти это, я использовал np.digitize для квантования ввода и возврата дискретного количества ячеек вместе с долей отсчетов для каждого ящика. Вы можете легко отредактировать, чтобы получить целое число отсчетов.

def compute_PMF(data)
    import numpy as np
    from collections import Counter
    _, bins = np.histogram(data, bins='auto', range=(data.min(), data.max()), density=False)
    h = Counter(np.digitize(data,bins) - 1)
    weights = np.asarray(list(h.values())) 
    weights = weights / weights.sum()
    values = np.asarray(list(h.keys()))
    return weights, values
####

Ссылки:

[1] https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html

[2] https://docs.scipy.org/doc/numpy/reference/generated/numpy.digitize.html

Сиргого
источник