返回介绍

第47单元 以 Python 的方式完成统计

发布于 2024-01-28 22:01:16 字数 4659 浏览 0 评论 0 收藏 0

Python对随机数和统计的支持分散在以下多个模块中:statistics、numpy.random、pandas和scipy.stats。

生成随机数

numpy.random模块中包含所有主要概率分布的随机数生成器。

本书在第1章中就指出,数据分析的代码应该是可复现的:任何人都应该能够使用相同的输入数据运行相同的程序,并获得相同的结果。因此,你应该始终使用seed()函数来初始化伪随机种子,否则,随机数生成器在每个程序运行时会产生不同的伪随机序列,这可能使结果难以乃至不可能复现。

import numpy.random as rnd
rnd.seed(z)

下面的函数产生均匀、正态以及二项分布的整数和实值随机数。这些函数都返回一个具有shape或size的numpy数组(shape是一个由各个维度组成的列表),除非size的参数设置为None。

rnd.uniform(low=0.0, high=1.0, size=None)
rnd.rand(shape) # 等同于uniform(0.0, 1.0, None)
rnd.randint(low, high=None, size=None)
rnd.normal(loc=0.0, scale=1.0, size=None)
rnd.randn(shape) # 等同于normal(0.0, 1.0, shape)
rnd.binomial(n, p, size=None)

当需要设置预测实验并将数据分为训练集和测试集时,二项分布是必不可少的(更多关于预测实验的内容,请参考第48单元)。令训练集的相对大小为p,测试集的相对大小为1-p。你可以准备一个二值序列,然后将其转换为True和False值的布尔序列,最后通过pandas的frame选出两个集合:

selection = rnd.binomial(1, p, size=len(data)).astype(bool)
training = df[selection]
testing = df[-selection]

计算统计度量

作为一种快速而随性的计算统计度量的方式,statistics模块(本书首次提及该模块是在第14单元)提供低端函数mean()和stdev()。

pandas的frame和series具有用于计算与其他frame和series的相关性和协方差的函数,也有计算frame的列之间的两两相关性和协方差(但没有p值)以及其他统计度量的函数。

让我们再次使用第31单元中被转换为frame的NIAAA监控报告,来探索pandas的统计功能。(我们不是醉汉!我们是数据科学家:一旦得到了一个好的数据集,我们将最大限度地使用它!)准备两个series,然后计算它们的相关性、协方差和偏斜度:

   beer_seriesNY = alco.ix['New York']['Beer']
   beer_seriesCA = alco.ix['California']['Beer']

   beer_seriesNY.corr(beer_seriesCA)

➾ 0.97097785391654789

   beer_seriesCA.cov(beer_seriesNY)

➾ 0.017438162878787872

   [x.skew() for x in (beer_seriesCA, beer_seriesNY)]

➾  [0.16457291293004678, 0.32838100586347024]

我们也可以对frame应用相同的函数:

   frameNY = alco.ix['New York']

   frameNY.skew()

➾ Beer       0.328381Wine       0.127308Spirits    0.656699dtype: float64

   frameNY.corr() # 所有的两两相关性

➾              Beer      Wine   SpiritsBeer     1.000000  0.470690  0.908969Wine     0.470690  1.000000  0.611923Spirits  0.908969  0.611923  1.000000

   frameNY.cov() # 所有的两两协方差

➾              Beer      Wine   SpiritsBeer     0.016103  0.002872  0.026020Wine     0.002872  0.002312  0.006638Spirits  0.026020  0.006638  0.050888

后两个函数分别返回包含所有两两相关性及所有两两协方差的frame。

我们还可以将一个series和一个frame相关联,也可以将一个frame和另一个frame相关联。例如,使用美国人口普查局2000年至2009年间的数据1,分析纽约的酒精消费与国家人口之间是否存在某种相关性:

1www.census.gov/popest/data/historical/2000s/vintage_2009/state.html

   # 移除最后两行:因为这两行数据包含了对未来的估计值
   pop_seriesNY = pop.ix["New York"][:-2]
   # 将索引由日期变为整数年
   pop_seriesNY.index = pop_seriesNY.index.str.split().str[-1].astype(int)

   frameNY.ix[2000:2009].corrwith(pop_seriesNY)

➾ Beer      -0.520878Wine       0.936026Spirits    0.957697dtype: float64

请注意,frame和series中的行是以相反的顺序排列的。pandas非常智能,可以使用行索引来匹配正确的行。当然,真正起作用的是数据对齐机制。(第36单元详细讨论了数据对齐方式。)

要估计相关性的显著程度,请使用scipy.stats模块中的pearsonr()函数。该函数返回相关性和p值,但它不能与pandas的frame集成,也不支持索引,所以你需要将索引对齐并将结果转换回frame。

   from scipy.stats import pearsonr
   # 手动排列索引
   pop_sorted = pop_seriesNY.sort_index()
   alco_10 = alco.ix['New York'][-10:]
   # 使用列表解析的方式计算所有的相关性和p值
   corrs = [(bev,) + pearsonr(alco_10[bev], pop_sorted)
            for bev in alco_10.columns]
   # 将列表转换为frame
   pd.DataFrame(corrs, columns=("bev", "r", "p-value")).set_index("bev")

➾                r  p-valuebevBeer   -0.520878  0.122646Wine    0.936026  0.000068Spirits 0.957697  0.000013

请注意,“啤酒”相关性的p值是非常高的。根据第46单元中的表6,我们得出结论,人口与啤酒消费之间不存在线性关系。

我们现在完全有能力重新审视第36单元中的交叉表的例子。根据交叉表的分析,我们得出2009年的人均啤酒消费量和葡萄酒消费量可能是线性独立的。皮尔逊相关性分析完全证实了我们的说法:

   alco2009.corr()

➾             Beer      Wine   SpiritsBeer    1.000000 -0.031560  0.452279Wine   -0.031560  1.000000  0.599791Spirits 0.452279  0.599791  1.000000

相关性具有极高的p值,这为我们的假设提供了致命一击:

   pearsonr(alco2009["Wine"], alco2009["Beer"])

➾ (-0.031560488300856844, 0.82598481310787297)

下面的散点图解释了原因:这些点差不多散布在整幅图上,没有特定的顺序或规律。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文