【Python】不用numpy用純python求極差、平均數、中位數、眾數與方差,python的列印到控制檯
原文連結:https://blog.csdn.net/yongh701/article/details/50150619
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
公式:或者(就是在《概率論與數理統計》中那條,方差就是平方的期望-期望的平方)
因此,根據上述的理論,得到如下的程式碼:
-
#-*-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位小數的方式輸出。