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



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



plt.hist(myarray, normed=True)


а также:



plt.hist(myarray, normed=1)


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



спасибо!

835   4  

4 ответов:

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

я попробовал следующий:

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, density=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) вернулся около 7.2767.

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

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

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

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

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

но я не смог найти способ заставить бары имитировать функцию histtype="step" 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 достигло необходимого результата.

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

вот еще одно простое решение, используя 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

Comments

    Ничего не найдено.