验证正态分布pandas序列经验法则:均值±标准差占比计算疑问
验证正态分布经验法则的问题
我拥有一个服从正态分布的pandas Series对象s,该序列包含100个数据。我希望验证经验法则:即68%、95%、99.7%的数据分别落在均值±1、±2、±3标准差范围内。
我编写了如下代码生成数据:
import pandas as pd from pandas import Series, DataFrame import numpy as np np.random.seed(0) s = Series(np.random.normal(0, 100, 100))
在验证68%的数据落在均值±1标准差范围内时,我采用了如下计算方式:
s1 = s[s>= (s.mean() - s.std())].count() s2 = s[s<= (s.mean() + s.std())].count() percentage = (s1 + s2)/s.count()
得到的percentage值为1.68463。我有三个疑问:
- 我的±1标准差占比计算方式是否正确?
- 为何结果是1.68463,而非经验法则中的68.463?
- 是否存在更优的占比计算方法?
问题解答
1. 计算方式不正确
你的逻辑错误在于重复统计了数据:s1是大于等于均值-1标准差的数量,s2是小于等于均值+1标准差的数量,这两个集合有大量重叠(大部分数据同时满足两个条件),直接相加会把中间符合条件的数据算两次,导致结果严重偏大。正确逻辑应该是统计同时满足s >= 均值-1标准差且s <= 均值+1标准差的数据数量。
2. 结果异常的原因
因为重复计算了重叠数据,1.68463是把中间符合条件的数据加了两次后除以总数量的结果。修正计算方式后,你生成的这个数据集实际符合±1标准差范围的数据有70个,占比0.7(70%),和经验法则的68%接近(样本量只有100,存在抽样误差)。
3. 更优的计算方法
有几种简洁高效的实现方式:
- 方法一:布尔索引直接筛选区间
lower = s.mean() - s.std() upper = s.mean() + s.std() percentage = s[(s >= lower) & (s <= upper)].count() / s.count() - 方法二:使用
between()方法
pandas的between()可以直接筛选区间内的数据,且利用布尔值的均值直接得到比例,代码更简洁:percentage = s.between(s.mean() - s.std(), s.mean() + s.std()).mean() - 批量验证三个区间
若要一次性验证±1、±2、±3标准差的占比,用循环简化代码:for n in [1,2,3]: lower = s.mean() - n * s.std() upper = s.mean() + n * s.std() ratio = s.between(lower, upper).mean() print(f"±{n}标准差范围内的占比: {ratio:.3%}")
内容的提问来源于stack exchange,提问作者bib
相关产品推荐
相关产品推荐

