階教程:17_statistics 模塊 —— 新手完全指南)
statistics是 Python 3.4 版本開始加入的內(nèi)置標(biāo)準(zhǔn)庫專門用來做基礎(chǔ)的統(tǒng)計(jì)計(jì)算不需要額外安裝導(dǎo)入就能用。它封裝了我們?nèi)粘W畛S玫慕y(tǒng)計(jì)量均值、中位數(shù)、眾數(shù)、方差、標(biāo)準(zhǔn)差等不用自己寫循環(huán)、寫公式計(jì)算一行代碼就能得到準(zhǔn)確結(jié)果非常適合新手處理簡單的數(shù)據(jù)分析場景。本文會(huì)按「集中趨勢 → 離散程度」的邏輯逐個(gè)講解每個(gè)函數(shù)每個(gè)函數(shù)都配可運(yùn)行示例 逐行解釋 新手避坑指南零基礎(chǔ)也能完全吃透。一、模塊基礎(chǔ)說明1. 模塊定位內(nèi)置模塊Python 安裝完就有不需要pip install適用場景簡單的基礎(chǔ)統(tǒng)計(jì)計(jì)算處理小規(guī)模數(shù)值數(shù)據(jù)優(yōu)勢代碼簡潔、結(jié)果準(zhǔn)確、不用自己實(shí)現(xiàn)統(tǒng)計(jì)公式2. 導(dǎo)入方式# 方式1導(dǎo)入整個(gè)模塊推薦新手用不容易混淆函數(shù)來源 import statistics # 方式2單獨(dú)導(dǎo)入需要的函數(shù) from statistics import mean, stdev, median3. 前置約定所有統(tǒng)計(jì)函數(shù)的輸入基本都是「數(shù)值型可迭代對象」比如整數(shù) / 浮點(diǎn)數(shù)組成的列表、元組。 ?? 新手坑不能傳入空列表、不能傳入字符串 / None 等非數(shù)值類型否則會(huì)直接報(bào)錯(cuò)。二、第一類集中趨勢指標(biāo)描述數(shù)據(jù)的中心水平集中趨勢就是找一組數(shù)據(jù)的「代表值 / 中心值」比如我們常說的平均分、中間分、出現(xiàn)最多的分?jǐn)?shù)都屬于這類指標(biāo)。1. mean ()算術(shù)平均數(shù)功能計(jì)算一組數(shù)據(jù)的算術(shù)平均值也就是我們最常用的「總和 ÷ 個(gè)數(shù)」是最基礎(chǔ)、最常用的平均指標(biāo)。語法statistics.mean(數(shù)值序列)示例計(jì)算班級考試平均分import statistics # 班級8名同學(xué)的數(shù)學(xué)成績 scores [85, 92, 78, 90, 88, 76, 95, 82] # 計(jì)算算術(shù)平均分 avg statistics.mean(scores) print(f班級數(shù)學(xué)平均分{avg})運(yùn)行結(jié)果plaintext班級數(shù)學(xué)平均分85.75代碼解釋先定義成績列表scores一共 8 個(gè)數(shù)值statistics.mean(scores)自動(dòng)計(jì)算(8592789088769582) ÷ 8 686 ÷ 8 85.75結(jié)果是浮點(diǎn)數(shù)類型哪怕剛好整除也會(huì)返回 float注意事項(xiàng)序列不能為空否則報(bào)錯(cuò)StatisticsError: mean requires at least one data point只能放數(shù)值int/float放字符串會(huì)報(bào)類型錯(cuò)誤容易受極端值影響比如加一個(gè) 0 分平均分被大幅拉低2. median ()中位數(shù)功能把數(shù)據(jù)從小到大排序后位于正中間位置的數(shù)值。如果數(shù)據(jù)個(gè)數(shù)是偶數(shù)取中間兩個(gè)數(shù)的平均值。 中位數(shù)的優(yōu)勢是不受極端值影響適合數(shù)據(jù)里有異常大 / 異常小值的場景。語法statistics.median(數(shù)值序列)示例 1奇數(shù)個(gè)數(shù)據(jù)import statistics # 9個(gè)同學(xué)的成績奇數(shù)個(gè) scores [76, 78, 82, 85, 88, 90, 92, 95, 100] mid statistics.median(scores) print(f成績中位數(shù){mid})運(yùn)行結(jié)果成績中位數(shù)88解釋9 個(gè)數(shù)排序后第 5 個(gè)位置的數(shù)就是中位數(shù)也就是 88。示例 2偶數(shù)個(gè)數(shù)據(jù)import statistics # 8個(gè)同學(xué)的成績偶數(shù)個(gè) scores [76, 78, 82, 85, 88, 90, 92, 95] mid statistics.median(scores) print(f成績中位數(shù){mid})運(yùn)行結(jié)果成績中位數(shù)86.5解釋8 個(gè)數(shù)排序后中間是第 4 個(gè)和第 5 個(gè)取兩者的平均值(8588) ÷ 2 86.5。拓展低中位數(shù)、高中位數(shù)還有兩個(gè)衍生函數(shù)適合需要取整數(shù)的場景median_low()偶數(shù)個(gè)時(shí)取中間偏小的那個(gè)數(shù)median_high()偶數(shù)個(gè)時(shí)取中間偏大的那個(gè)數(shù)scores [76, 78, 82, 85, 88, 90, 92, 95] print(statistics.median_low(scores)) # 85 print(statistics.median_high(scores)) # 883. mode ()眾數(shù)功能一組數(shù)據(jù)中出現(xiàn)次數(shù)最多的數(shù)值用來反映最普遍的情況。語法statistics.mode(數(shù)值序列)示例統(tǒng)計(jì)出現(xiàn)次數(shù)最多的分?jǐn)?shù)import statistics scores [85, 92, 85, 90, 88, 92, 92, 82] most statistics.mode(scores) print(f出現(xiàn)次數(shù)最多的分?jǐn)?shù){most})運(yùn)行結(jié)果出現(xiàn)次數(shù)最多的分?jǐn)?shù)92解釋92 出現(xiàn)了 3 次是出現(xiàn)次數(shù)最多的所以眾數(shù)是 92。?? 新手頭號(hào)大坑多個(gè)眾數(shù)會(huì)報(bào)錯(cuò)如果有兩個(gè)及以上的數(shù)值出現(xiàn)次數(shù)并列最多mode()會(huì)直接報(bào)錯(cuò)StatisticsError。 解決方法用multimode()函數(shù)返回所有眾數(shù)組成的列表Python 3.8 支持。示例多個(gè)眾數(shù)的處理import statistics scores [85, 92, 85, 92, 88, 76] # 85和92都出現(xiàn)了2次并列最多 # 錯(cuò)誤寫法mode會(huì)報(bào)錯(cuò) # print(statistics.mode(scores)) # 正確寫法multimode返回所有眾數(shù) all_modes statistics.multimode(scores) print(f所有眾數(shù){all_modes})運(yùn)行結(jié)果所有眾數(shù)[85, 92]4. geometric_mean ()幾何平均數(shù)功能幾何平均數(shù)多用于計(jì)算平均增長率、平均比例比如連續(xù)多年的收益率、人口增長率比算術(shù)平均更適合描述增長類數(shù)據(jù)。 公式n 個(gè)數(shù)值相乘后開 n 次方。注意Python 3.8 才支持這個(gè)函數(shù)所有數(shù)據(jù)必須是正數(shù)。示例計(jì)算平均年收益率import statistics # 某基金連續(xù)3年的收益率第一年漲10%、第二年漲20%、第三年漲15% # 轉(zhuǎn)化為增長倍數(shù)1.1、1.2、1.15 growth_rates [1.1, 1.2, 1.15] avg_growth statistics.geometric_mean(growth_rates) print(f年均增長倍數(shù){avg_growth:.4f}) print(f年均收益率{(avg_growth - 1)*100:.2f}%)運(yùn)行結(jié)果年均增長倍數(shù)1.1487 年均收益率14.87%解釋三年的復(fù)利平均下來相當(dāng)于每年穩(wěn)定漲 14.87%。5. harmonic_mean ()調(diào)和平均數(shù)功能調(diào)和平均數(shù)多用于計(jì)算平均速度、平均單價(jià)等場景比如路程相同的情況下計(jì)算平均速度。示例計(jì)算往返平均速度import statistics # 去程速度60km/h返程速度40km/h路程相同求平均速度 speeds [60, 40] avg_speed statistics.harmonic_mean(speeds) print(f往返平均速度{avg_speed:.2f} km/h)運(yùn)行結(jié)果往返平均速度48.00 km/h解釋調(diào)和平均計(jì)算的是「相同距離下的平均速度」結(jié)果 48 是正確的不是簡單的 (6040)/250。三、第二類離散程度指標(biāo)描述數(shù)據(jù)的波動(dòng)大小離散程度用來衡量一組數(shù)據(jù)「散不散、波動(dòng)大不大」。比如兩個(gè)班平均分都是 85一個(gè)班分?jǐn)?shù)都集中在 80-90另一個(gè)班有考 60 也有考 100 的后者波動(dòng)更大離散程度更高。前置必懂總體 vs 樣本這是新手最容易混淆的點(diǎn)先通俗講清楚總體你手里的數(shù)據(jù)就是全部研究對象比如全班所有人的成績計(jì)算波動(dòng)用「總體方差 / 總體標(biāo)準(zhǔn)差」函數(shù)名帶p前綴p population樣本你手里的數(shù)據(jù)只是從整體里抽出來的一部分比如從全年級抽 10 個(gè)學(xué)生的成績用來估計(jì)全年級的波動(dòng)用「樣本方差 / 樣本標(biāo)準(zhǔn)差」分母是 n-1結(jié)果比總體的稍大更嚴(yán)謹(jǐn)。四個(gè)函數(shù)對應(yīng)關(guān)系類型方差函數(shù)標(biāo)準(zhǔn)差函數(shù)總體pvariance()pstdev()樣本variance()stdev()方差和標(biāo)準(zhǔn)差的關(guān)系標(biāo)準(zhǔn)差 √方差 標(biāo)準(zhǔn)差的單位和原數(shù)據(jù)一致比方差更直觀日常描述波動(dòng)更常用標(biāo)準(zhǔn)差。1. pvariance ()總體方差功能計(jì)算總體方差描述整組數(shù)據(jù)偏離均值的程度數(shù)值越大數(shù)據(jù)越分散。語法statistics.pvariance(數(shù)值序列, 均值可選)示例計(jì)算全班成績的總體方差import statistics # 全班8名同學(xué)的成績這就是全部總體 scores [85, 92, 78, 90, 88, 76, 95, 82] # 計(jì)算總體方差 p_var statistics.pvariance(scores) print(f成績總體方差{p_var:.2f})運(yùn)行結(jié)果成績總體方差35.942. pstdev ()總體標(biāo)準(zhǔn)差功能總體方差開平方就是總體標(biāo)準(zhǔn)差單位和原數(shù)據(jù)一樣這里是「分」比方差更直觀好理解。示例import statistics scores [85, 92, 78, 90, 88, 76, 95, 82] p_std statistics.pstdev(scores) print(f成績總體標(biāo)準(zhǔn)差{p_std:.2f} 分)運(yùn)行結(jié)果成績總體標(biāo)準(zhǔn)差5.99 分解釋可以簡單理解為班級里大部分同學(xué)的分?jǐn)?shù)都在平均分上下浮動(dòng)約 6 分左右。3. variance ()樣本方差功能計(jì)算樣本方差用于抽樣數(shù)據(jù)估計(jì)總體波動(dòng)分母是 n-1n 是數(shù)據(jù)個(gè)數(shù)。示例抽樣估計(jì)年級成績波動(dòng)import statistics # 從全年級抽了8個(gè)同學(xué)的成績樣本數(shù)據(jù) sample_scores [85, 92, 78, 90, 88, 76, 95, 82] # 樣本方差 sample_var statistics.variance(sample_scores) print(f樣本方差{sample_var:.2f})運(yùn)行結(jié)果樣本方差41.07可以看到同樣的數(shù)據(jù)樣本方差41.07比總體方差35.94大這是正常的因?yàn)闃颖竟烙?jì)總體需要留有余量。4. stdev ()樣本標(biāo)準(zhǔn)差功能樣本方差開平方是最常用的波動(dòng)描述指標(biāo)。示例import statistics sample_scores [85, 92, 78, 90, 88, 76, 95, 82] sample_std statistics.stdev(sample_scores) print(f樣本標(biāo)準(zhǔn)差{sample_std:.2f} 分)運(yùn)行結(jié)果樣本標(biāo)準(zhǔn)差6.41 分四、拓展quantiles () 分位數(shù)Python 3.8功能把數(shù)據(jù)按大小排序后分成 n 等份得到分割點(diǎn)的數(shù)值最常用的是四分位數(shù)分成 4 份可以快速了解數(shù)據(jù)的分布區(qū)間。示例計(jì)算成績的四分位數(shù)import statistics scores [76, 78, 82, 85, 88, 90, 92, 95, 100] # n4 表示分成4等份得到3個(gè)四分位點(diǎn) q statistics.quantiles(scores, n4) print(f第一四分位數(shù)Q1{q[0]}) # 25%位置 print(f第二四分位數(shù)Q2{q[1]}) # 50%位置就是中位數(shù) print(f第三四分位數(shù)Q3{q[2]}) # 75%位置運(yùn)行結(jié)果第一四分位數(shù)Q180.0 第二四分位數(shù)Q288.0 第三四分位數(shù)Q393.5解釋25% 的同學(xué)分?jǐn)?shù)低于 80 分75% 的同學(xué)低于 93.5 分。五、綜合實(shí)戰(zhàn)案例班級成績完整統(tǒng)計(jì)下面是一個(gè)完整的小例子用statistics模塊一次性算出所有常用統(tǒng)計(jì)量非常適合日常簡單分析。import statistics # 某班10名同學(xué)的期末數(shù)學(xué)成績 scores [72, 85, 91, 68, 95, 85, 79, 88, 91, 91] print( 班級成績統(tǒng)計(jì) ) print(f平均分{statistics.mean(scores):.2f} 分) print(f中位數(shù){statistics.median(scores)} 分) print(f眾數(shù){statistics.mode(scores)} 分) print(f最高分{max(scores)} 分) print(f最低分{min(scores)} 分) print(f總體標(biāo)準(zhǔn)差{statistics.pstdev(scores):.2f} 分) print(f總體方差{statistics.pvariance(scores):.2f})運(yùn)行結(jié)果 班級成績統(tǒng)計(jì) 平均分84.50 分 中位數(shù)86.5 分 眾數(shù)91 分 最高分95 分 最低分68 分 總體標(biāo)準(zhǔn)差8.52 分 總體方差72.65六、新手高頻易錯(cuò)點(diǎn)總結(jié)傳入空列表報(bào)錯(cuò)所有統(tǒng)計(jì)函數(shù)都要求序列至少有 1 個(gè)數(shù)據(jù)空列表會(huì)觸發(fā)StatisticsError。非數(shù)值類型報(bào)錯(cuò)列表里不能有字符串、None、布爾值以外的非數(shù)值類型否則報(bào)類型錯(cuò)誤。眾數(shù)多個(gè)時(shí)報(bào)錯(cuò)并列最多的眾數(shù)有多個(gè)時(shí)mode()會(huì)報(bào)錯(cuò)改用multimode()獲取所有眾數(shù)列表。總體和樣本搞混數(shù)據(jù)是全部研究對象 → 用pvariance/pstdev數(shù)據(jù)是抽樣樣本 → 用variance/stdev日常小數(shù)據(jù)、只是描述當(dāng)前這組數(shù)據(jù)用總體的即可。低版本 Python 不支持新函數(shù)geometric_mean、harmonic_mean、multimode、quantiles都是 Python 3.8 才有的低版本會(huì)報(bào)錯(cuò)。復(fù)雜統(tǒng)計(jì)場景不適用statistics只適合基礎(chǔ)統(tǒng)計(jì)復(fù)雜的數(shù)據(jù)分析、矩陣運(yùn)算、回歸分析等建議用numpy、pandas第三方庫。