Я хотел бы построить нормализованную гистограмму из вектора с помощью matplotlib. Я пробовал следующее:
plt.hist(myarray, normed=True)
так же как:
plt.hist(myarray, normed=1)
но ни одна из опций не создает ось Y из [0, 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, 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) / len(myarray) plt.hist(myarray, weights=weights)
Надеюсь, что это поможет, хотя нить довольно старая ...
Примечание для Python 2.x: добавьте приведение к
float()
одному из операторов деления, иначе вы получите нули из-за целочисленного деления.источник
array_like
а не массив numpy, вам нужно будет выполнить приведениеlen(myarray)
кfloat
.Я знаю, что этот ответ слишком поздно, учитывая, что вопрос датирован 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
источник