Подтвердить что ты не робот

Построение гистограмм, высота баров которых равна 1 в matplotlib

Я хотел бы построить нормализованную гистограмму из вектора, используя matplotlib. Я попробовал следующее:

plt.hist(myarray, normed=True)

а также:

plt.hist(myarray, normed=1)

но ни одна из них не создает ось у от [0, 1], так что высота гистограммы суммы гистограммы равна 1. Я хотел бы создать такую ​​гистограмму - как я могу это сделать?

спасибо!

4b9b3361

Ответ 1

Было бы более полезно, если бы вы представили более полный рабочий (или в этом случае нерабочий) пример.

Я попробовал следующее:

import numpy as np
import matplotlib.pyplot as plt

x = np.random.randn(1000)

fig = plt.figure()
ax = fig.add_subplot(111)
n, bins, rectangles = ax.hist(x, 50, normed=True)
fig.canvas.draw()
plt.show()

Это действительно приведет к гистограмме гистограммы с осью y, которая идет от [0,1].

Далее, согласно документации hist (т.е. ax.hist? от ipython), я думаю, что сумма тоже прекрасна:

*normed*:
If *True*, the first element of the return tuple will
be the counts normalized to form a probability density, i.e.,
``n/(len(x)*dbin)``.  In a probability density, the integral of
the histogram should be 1; you can verify that with a
trapezoidal integration of the probability density function::

    pdf, bins, patches = ax.hist(...)
    print np.sum(pdf * np.diff(bins))

Предоставляя эту попытку после команд выше:

np.sum(n * np.diff(bins))

Я получаю возвращаемое значение 1.0, как и ожидалось. Помните, что normed=True не означает, что сумма значения на каждом баре будет равна единице, а интеграл по барам будет равен единице. В моем случае np.sum(n) возвращается approx 7.2767.

Ответ 2

Если вы хотите, чтобы сумма всех баров была равна единице, вес каждого бункера по общему числу значений:

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)

Надеюсь, что это поможет, хотя поток довольно старый...

Ответ 3

Я знаю, что этот ответ слишком поздний, учитывая, что вопрос датирован 2010 годом, но я столкнулся с этим вопросом, поскольку сам столкнулся с подобной проблемой. Как уже было сказано в ответе, normed = True означает, что общая площадь под гистограммой равна 1, но сумма высот не равна 1. Однако я хотел, для удобства физической интерпретации гистограммы, сделать один с суммой высот, равной 1.

Я нашел подсказку в следующем вопросе - Python: гистограмма с областью, нормированной на нечто, отличное от 1

Но мне не удалось найти способ сделать бары, имитирующие histtype = "step" feature hist(). Это отвлекло меня от: Matplotlib - ступенчатая гистограмма с уже обработанными данными

Если сообщество считает это приемлемым, я хотел бы предложить решение, которое синтезирует идеи из обоих вышеперечисленных сообщений.

import matplotlib.pyplot as plt

# Let X be the array whose histogram needs to be plotted.
nx, xbins, ptchs = plt.hist(X, bins=20)
plt.clf() # Get rid of this histogram since not the one we want.

nx_frac = nx/float(len(nx)) # Each bin divided by total number of objects.
width = xbins[1] - xbins[0] # Width of each bin.
x = np.ravel(zip(xbins[:-1], xbins[:-1]+width))
y = np.ravel(zip(nx_frac,nx_frac))

plt.plot(x,y,linestyle="dashed",label="MyLabel")
#... Further formatting.

Это работало чудесно для меня, хотя в некоторых случаях я заметил, что левый самый "бар" или правый "бар" гистограммы не закрывается, касаясь самой нижней точки оси Y. В таком случае добавление элемента 0 в сторону попрошайства или конца y обеспечило необходимый результат.

Просто подумал, что поделюсь своим опытом. Спасибо.

Ответ 4

Вот еще одно простое решение с использованием метода np.histogram().

myarray = np.random.random(100)
results, edges = np.histogram(myarray, normed=True)
binWidth = edges[1] - edges[0]
plt.bar(edges[:-1], results*binWidth, binWidth)

Вы действительно можете проверить, что суммарные суммы до 1:

> print sum(results*binWidth)
1.0