計算常用統計量的類

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

公式:或者(就是在《概率論與數理統計》中那條,方差就是平方的期望-期望的平方)


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[int(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 i in count_dict:
                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,這個字典中,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位小數的方式輸出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章