Построение гистограмм, высота баров которых равна 1 в matplotlib
Я хотел бы построить нормализованную гистограмму из вектора, используя matplotlib. Я попробовал следующее:
plt.hist(myarray, normed=True)
а также:
plt.hist(myarray, normed=1)
но ни одна из них не создает ось у от [0, 1], так что высота гистограммы суммы гистограммы равна 1. Я хотел бы создать такую гистограмму - как я могу это сделать?
спасибо!
Ответы
Ответ 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