pylab.hist(数据,规范=1)。规范化似乎工作不正确
Posted
技术标签:
【中文标题】pylab.hist(数据,规范=1)。规范化似乎工作不正确【英文标题】:pylab.hist(data, normed=1). Normalization seems to work incorrect 【发布时间】:2011-07-26 18:17:29 【问题描述】:我正在尝试使用参数 normed=1 创建直方图
例如:
import pylab
data = ([1,1,2,3,3,3,3,3,4,5.1])
pylab.hist(data, normed=1)
pylab.show()
我预计 bin 的总和为 1。但是,其中一个 bin 比 1 大。这个标准化做了什么?以及如何创建一个直方图的归一化使得直方图的积分等于 1?
【问题讨论】:
也可以试试pylab.hist(data, bins=5, range=(1, 6), normed=1)
。这将导致 bin 宽度为 1。
"bin 的总和为 1。但是,其中一个 bin 大于 1" -> 这并不矛盾!
【参考方案1】:
请参阅我的另一篇文章,了解如何使直方图中所有 bin 的总和等于 1: https://***.com/a/16399202/1542814
复制和粘贴:
weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)
myarray 包含您的数据的位置
【讨论】:
如果你在做频率直方图,这是最好的方法! 仅供参考,如果您使用上述方法,请务必保留normed=0
。
与this example 中的格式化程序完美结合使用(使用normed
代替权重;权重的工作原理与bin 大小无关,而normed
/density
需要大小统一的bin,来自documentation)。
太棒了!最好的方式【参考方案2】:
根据documentation normed:如果为 True,则结果是 bin 处的概率密度函数的值,归一化使得范围内的积分为 1。请注意,直方图值的总和将不等于 1,除非选择了统一宽度的 bin;它不是概率质量函数。这是来自 numpy doc,但对于 pylab 应该是相同的。
In []: data= array([1,1,2,3,3,3,3,3,4,5.1])
In []: counts, bins= histogram(data, normed= True)
In []: counts
Out[]: array([ 0.488, 0., 0.244, 0., 1.22, 0., 0., 0.244, 0., 0.244])
In []: sum(counts* diff(bins))
Out[]: 0.99999999999999989
所以简单的标准化是根据以下文档完成的:
In []: counts, bins= histogram(data, normed= False)
In []: counts
Out[]: array([2, 0, 1, 0, 5, 0, 0, 1, 0, 1])
In []: counts_n= counts/ sum(counts* diff(bins))
In []: counts_n
Out[]: array([ 0.488, 0., 0.244, 0., 1.22 , 0., 0., 0.244, 0., 0.244])
【讨论】:
@smirnoffs:你认为它不能大于 1 的理由是什么?谢谢 @eat 归一化直方图,据我所知,是一个概率密度函数。概率不能超过 1。 @smirnoffs:你能提供一些链接来备份你对标准化直方图的定义吗? FWIW 从文档中可以看出标准化是如何工作的。counts* diff(bins)
为您提供所需的内容。谢谢
概率 densities 可以是任何非负数,只要该范围内的 integral(不是总和)等于 1。跨度>
这个答案是指numpy.histogram,而不是pylab.hist【参考方案3】:
我认为您将垃圾箱高度与垃圾箱内容混淆了。您需要添加每个 bin 的内容,即所有 bin 的 height*width。那应该 = 1。
【讨论】:
所以为了澄清大家,你会在 OP 的直方图上放置什么作为 y 轴标签?【参考方案4】:这个标准化做了什么?
为了规范化序列,您必须考虑 bin 大小。
根据documentation,bin 的默认数量为 10。因此,bin 大小为(data.max() - data.min() )/10
,即 0.41。
如果是normed=1
,那么条形的高度就是这样的总和,乘以 0.41,得到 1。这就是积分时发生的情况。
以及如何创建一个直方图的归一化使得直方图的积分等于 1?
我认为您希望直方图的总和(而不是其积分)等于 1。在这种情况下,最快的方法似乎是:
h = plt.hist(data)
norm = sum(data)
h2 = [i/norm for i in h[0]]
plt.bar(h[1],h2)
【讨论】:
【参考方案5】:我遇到了同样的问题,在解决它的同时又出现了另一个问题:如何将归一化的 bin 频率绘制为百分比,并在 rounded 值上加上刻度。我在这里发布它以防它对任何人有用。在我的示例中,我选择 10% (0.1) 作为 y 轴的最大值,并选择 10 个步骤(一个从 0% 到 1%,一个从 1% 到 2%,依此类推)。诀窍是在 data 计数处设置刻度(这是plt.hist
的输出列表n
),接下来将使用FuncFormatter
类将其转换为百分比。这是我所做的:
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
fig, ax = plt.subplots()
# The required parameters
num_steps = 10
max_percentage = 0.1
num_bins = 40
# Calculating the maximum value on the y axis and the yticks
max_val = max_percentage * len(data)
step_size = max_val / num_steps
yticks = [ x * step_size for x in range(0, num_steps+1) ]
ax.set_yticks( yticks )
plt.ylim(0, max_val)
# Running the histogram method
n, bins, patches = plt.hist(data, num_bins)
# To plot correct percentages in the y axis
to_percentage = lambda y, pos: str(round( ( y / float(len(data)) ) * 100.0, 2)) + '%'
plt.gca().yaxis.set_major_formatter(FuncFormatter(to_percentage))
plt.show()
地块
标准化之前:y 轴单位是 x 轴上 bin 间隔内的样本数:
标准化后:y 轴单位是 bin 值的频率,作为所有样本的百分比
【讨论】:
【参考方案6】:还有numpy.histogram
。如果设置density=True
,输出会被归一化。
normed : bool, optional
由于令人困惑/错误的行为,该关键字在 Numpy 1.6 中已弃用。它将在 Numpy 2.0 中删除。请改用密度关键字。如果为 False,则结果将包含每个 bin 中的样本数。如果为 True,则结果是 bin 处的概率密度函数的值,归一化以使范围内的积分为 1。改用密度。
density : bool, optional
如果为 False,则结果将包含每个 bin 中的样本数。如果为 True,则结果是 bin 处的概率密度函数值,经过归一化处理,使得范围内的积分为 1。请注意,除非选择了统一宽度的 bin,否则直方图值的总和将不等于 1;它不是概率质量函数。如果给定,则覆盖 normed 关键字。
【讨论】:
【参考方案7】:你的期望是错误的
垃圾箱高度的总和乘以它的宽度等于一。或者,正如您所说的正确,integral 必须是一个,不是您要集成的功能。
是这样的:概率(如“人在 20 到 40 岁之间的概率是……%”)是积分(“从 20 到 40 岁” ) 在概率密度上。 bins 高度显示概率密度,而宽度乘以高度显示某个点在此 bin 中的概率(您将常数假设函数、bin 的高度、从 bin 的开头到 bin 的结尾积分)。高度本身就是密度,不是概率。这是一个每个宽度的概率,当然可以高于一个。
简单示例:想象一个从 0 到 1 的概率密度函数,其值为 0 从 0 到 0.9。函数可能在 0.9 和 1 之间?如果您整合它,请尝试一下。它会高于 1。
顺便说一句:根据粗略的猜测,您的 hist 的高度乘以宽度的总和似乎大约为 1,不是吗?
【讨论】:
以上是关于pylab.hist(数据,规范=1)。规范化似乎工作不正确的主要内容,如果未能解决你的问题,请参考以下文章
sklearn StandardScaler 似乎无法正常工作