Python 汇总和计数进行统计分析,基于函数sum()
和len()
,可以给出算术平均值的简单定义,如下所示:
虽然这个定义很简洁,却不能用于可迭代对象,只能用于支持len()
函数的集合,这一点通过添加类型标示很容易发现。定义mean(items: Iterable) -> float
不成立,因为Iterable
类型不支持len()
函数。
诚然,对可迭代对象即使是求简单的平均值或者标准差都是很困难的。在Python中,我们要么实例化这些序列对象,要么转而使用一些更复杂的运算来完成求值。
正确的定义方法如下:
定义正确的类型标示以确保sum()
和len()
能正常工作。
下面的定义用简洁的表达式定义了平均值和标准差。
s0
、s1
和s2
是3种求和,实现过程都比较简单,结构也类似。通过它们可以很方便地算出平均值。计算标准差虽然稍复杂一些,但仍然可行。
更复杂的统计函数仍然具备这种良好的对称性,包括相关度和最小方差线性回归。
两个样本之间的相关度可以通过它们的标准值计算出来,如下所示:
计算过程是对每个样本x
减去平均值μ_x
,再除以标准差σ_x
,返回结果以σ为单位。大约2/3的情况下偏差在±1σ
范围内,偏差越大,出现的概率越小,超过±3σ
的概率则小于1/100。
如下所示使用该标量函数:
这里首先对变量d
中的值进行归一化,把计算结果实例化到一个列表中。使用生成器表达式,将标量函数z()
应用于序列对象。
利用上面的函数,可以给出函数mean()
和stdev()
的实现方法。
用类似的方法,如下改写前面3个求和函数:
尽管简洁明了,但该实现仍无法应用于可迭代对象。计算平均值时,需要对可迭代对象做一次汇总和一次计数。计算标准差时,需要做两次汇总和一次计数,针对这类统计相关的处理,必须将序列对象实例化,才能多次使用数据。
计算两个样本集相关性的函数实现如下:
上面的相关性计算用到了样本集的基本统计特征值:平均值和标准差。基于这些特征值,我们定义了两个生成器函数,计算每个样本集的归一值。接着用zip()
函数(见下个示例)把两个归一化序列中的元素组对,计算每对的乘积。这个乘积序列的平均值即表示两个样本集的相关度。
计算两个样本集之间的相关度如下所示:
这里的两个数据点序列xi
和yi
的相关度超过了0.99,表明二者关系紧密。
以上代码示例很好地体现了函数式编程的优点。我们用几个函数构建出了一个简单易用的统计模块,且每个函数只是简单的表达式。作为反例,不妨假设把corr()
函数写成一个长而复杂的表达式,函数内部有很多只用了一次的内部变量,用复制粘贴的方法把它们替换成各自代表的表达式。不难看出,虽然这里的corr()
函数仅由6行Python代码组成,但仍属于函数式编程。