python作为数据分析的利器,求极差、平均数、中位数、众数与方差是很常用的,然而,在python进行统计往往要使用外部的python库numpy,这个库不难装,然而,如果单纯只是求极差、平均数、中位数、众数与方差,还是自己写比较好,因为,给一个.py程序别人的机器,别人的机器上没有python库numpy,又要别人折腾一番,这很不好。不过看情况咯,如果你要处理上亿级的数据,还是配置一下外部的python库numpy吧。
先给大家回归一下极差、平均数、中位数、众数与方差是什么鬼:
1、极差:最大值与最小值之差。它是标志值变动的最大范围。英文:range
公式:R=Xmax-Xmin(其中,Xmax为最大值,Xmin为最小值)
2、平均数:一组数据中所有数据之和再除以数据的个数。反映数据集中趋势的一项指标。英文:average
公式:
3、中位数:对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,通常取最中间的两个数值的平均数作为中位数。英文:median
公式:从小到大排序为 则N为奇数时,N为偶数时,
4、众数:众数是样本观测值在频数分布表中频数最多的那一组的组中值,主要应用于大面积普查研究之中。英文:mode
例如:1,2,3,3,4的众数是3。
但是,如果有两个或两个以上个数出现次数都是最多的,那么这几个数都是这组数据的众数。
例如:1,2,2,3,3,4的众数是2和3。
还有,如果所有数据出现的次数都一样,那么这组数据没有众数。
例如:1,2,3,4,5没有众数。
5、方差:方差是实际值与期望值之差平方的平均值,方差是在概率论和统计方差衡量随机变量或一组数据是离散程度的度量。英文:variance
公式:或者(就是在《概率论与数理统计》中那条,方差就是平方的期望-期望的平方)
因此,根据上述的理论,得到如下的代码:
[python]
view plain
copy
#-*-coding:utf-8-*- import time; import random; class Math: #求极差 @staticmethod def range(l): return max(l)-min(l); #求平均数 @staticmethod def avg(l): return float(sum(l))/len(l); #求中位数 @staticmethod def median(l): l=sorted(l);#先排序 if len(l)%2==1: return l[len(l)/2]; else: return (l[len(l)/2-1]+l[len(l)/2])/2.0; #求众数 @staticmethod def mode(l): #统计list中各个数值出现的次数 count_dict={}; for i in l: if count_dict.has_key(i): count_dict[i]+=1; else: count_dict[i]=1; #求出现次数的最大值 max_appear=0 for v in count_dict.values(): if v>max_appear: max_appear=v; if max_appear==1: return; mode_list=[]; for k,v in count_dict.items(): if v==max_appear: mode_list.append(k); return mode_list; #求方差 @staticmethod def variance(l):#平方的期望-期望的平方 s1=0; s2=0; for i in l: s1+=i**2; s2+=i; return float(s1)/len(l)-(float(s2)/len(l))**2; #求方差2 @staticmethod def variance2(l):#平方-期望的平方的期望 ex=float(sum(l))/len(l); s=0; for i in l: s+=(i-ex)**2; return float(s)/len(l); #主函数,测试 arr=[1,2,3,2,3,1,4]; print "极差为:{0}".format(Math.range(arr)); print "平均数为:{0:.2f}".format(Math.avg(arr)); print "中位数为:{0}".format(Math.median(arr)); print "众数为:{0}".format(Math.mode(arr)); print "方差为:{0:.2f}".format(Math.variance(arr)); print "方差为:{0:.2f}".format(Math.variance2(arr)); print; #性能测试 arraylist=[]; for i in range(1,1000000): arraylist.append(i); random.shuffle(arraylist); time_start=time.time(); print "方差为:{0:.2f}".format(Math.variance(arraylist)); time_end=time.time(); print "{0}s".format(time_end-time_start); time_start=time.time(); print "方差为:{0:.2f}".format(Math.variance2(arraylist)); time_end=time.time(); print "{0}s".format(time_end-time_start);
运行结果如下:
关于这个程序有几点说明的:
(1)开头引入time与random主要是为了最后部分测试两种求方差的方式那种性能较优使用,一般情况下使用上述我自定义的Math类,无须引入任何python包。
(2)求任何一个统计量,用到除法,注意先将int先转float,否则精度损失严重,你是得到不到最后的正确答案的。
(3)python中自带有求list所有元素之和的sum,求list中的最值max,min,对list中的元素进行从小到大的排序sort()都用了,其余只能让我们自己现实了。
(4)这里无须考虑如果形式参数被传入一个字符串数组怎么办,因为这些工具类都是我们自己使用了,自己控制好要传递的数值,无须考虑这么多。
(5)求众数最艰难,因为用不到任何python自带的方法,还要返回一个list,因为众数的个数不定,统计数组中出现次数最多的数的时候,用到了python中的字典dict,《【Python】容器类》(点击打开链接),这个字典中,key是list中的数字,values是该数字出现的次数。然后要求出现次数的最大值,最后再求出改最大值对应的key。其中用count_dict.items()返回字典中的key-value对的数组集,count_dict.values()返回字典中的value集,当然同时也有count_dict.keys()返回key集。
(6)由于求方差的方法有两种,此程序在最后部分生成了一个百万级、打乱顺序的list,对两种求方差的方法进行测试,令人吃惊的是,万万没想到是我们愚蠢的人类最不爱用,也最难用的,最不好用的平方-期望的平方的期望,优于更好记忆的、更常用的平方的期望-期望的平方:。。从上述的运行结果可以看出这种求方差的方法速度是的一倍!这就是聪明的计算机与愚蠢的人类的区别吧~
(7)最后,python的打印到控制台,其实你完全可以print得更好的,你不换行还要在print后面补逗号吗,再print一个什么东东,或者将数值用str先转字符串才能与纯正的字符串连接起来,而字符串的format方法,配合print相当于C语言的printf,同时python的format用{0},{1}...代表后面的第0、1……参数。{0:.2f}代表这个参数以保留2位小数的方式输出。