據(jù)分析:從數(shù)據(jù)清洗到可視化報(bào)告全流程實(shí)踐)
簡(jiǎn)介一份圍繞氣象數(shù)據(jù)分析的實(shí)驗(yàn)型資源包面向數(shù)據(jù)分析初學(xué)者、選修課學(xué)生及需要完成課程設(shè)計(jì)的人群完整演示了從中國(guó)天氣網(wǎng)爬取指定城市天氣數(shù)據(jù)到清洗整理、繪制雷達(dá)圖與條形圖、并結(jié)合實(shí)際給出分析說(shuō)明的全流程。內(nèi)容包含可直接在Jupyter Notebook中運(yùn)行的源代碼、整理后的實(shí)驗(yàn)報(bào)告及全部可視化圖表既可用于課程作業(yè)模板也可作為爬蟲(chóng)入門(mén)和數(shù)據(jù)分析可視化的練習(xí)素材。資源共39個(gè)文件壓縮包僅1.69MB其中20張PNG圖片是最終生成的雷達(dá)圖、條形圖等分析圖表15個(gè)XML文件與4個(gè)rels文件共同構(gòu)成實(shí)驗(yàn)報(bào)告的Word源文檔結(jié)構(gòu)方便查看報(bào)告排版和圖片引用關(guān)系整體十分輕量下載后即可快速運(yùn)行。目前已有1853人學(xué)習(xí)下載。借助這套材料讀者可以掌握天氣數(shù)據(jù)采集、解析、分析與可視化的完整方法同時(shí)學(xué)習(xí)如何組織一份規(guī)范的實(shí)驗(yàn)報(bào)告并將這套流程遷移應(yīng)用到其他行業(yè)數(shù)據(jù)分析任務(wù)中。1. 氣象分析用一份氣象數(shù)據(jù)把數(shù)據(jù)分析全流程走通氣象分析這個(gè)項(xiàng)目名字聽(tīng)起來(lái)像氣象專(zhuān)業(yè)的事實(shí)際上是一套用 Python 做的數(shù)據(jù)分析項(xiàng)目實(shí)踐。核心就一句話拿一份真實(shí)氣象站點(diǎn)的逐日觀測(cè)數(shù)據(jù)把數(shù)據(jù)清洗、探索性分析、相關(guān)性檢驗(yàn)、可視化報(bào)告這條鏈路完整走一遍。為什么用它來(lái)練手因?yàn)闅庀髷?shù)據(jù)的字段語(yǔ)義非常明確氣溫、降水、濕度、風(fēng)速這些列每一列都看得懂物理含義缺失值和異常值模式清晰而且季節(jié)周期天然存在分析完對(duì)不對(duì)一眼就能驗(yàn)證。新手能在這里把 pandas、matplotlib 的基本功練扎實(shí)熟手可以拿它做插值試驗(yàn)、季節(jié)分解和殘差診斷。這份資源我按 Python 腳本、氣象樣本數(shù)據(jù)、報(bào)告實(shí)驗(yàn)?zāi)0迦龎K整理照著跑一遍就能產(chǎn)出一份像樣的數(shù)據(jù)分析實(shí)驗(yàn)報(bào)告。2. 數(shù)據(jù)獲取與清洗拿到氣象數(shù)據(jù)先處理三件事氣象數(shù)據(jù)在公開(kāi)渠道并不難找但真正決定報(bào)告質(zhì)量的是三大前提數(shù)據(jù)來(lái)源可靠、字段語(yǔ)義明確、缺失和異常處理得當(dāng)。這一章把資源里數(shù)據(jù)的常用來(lái)源、字段含義和清洗流程說(shuō)清楚順序?qū)α撕竺婊静环倒ぁ?.1 氣象數(shù)據(jù)的常見(jiàn)來(lái)源與字段選擇寫(xiě)數(shù)據(jù)分析報(bào)告的第一步不是寫(xiě)代碼是先搞清楚數(shù)據(jù)從哪來(lái)、每個(gè)字段代表什么。資源里用的是氣象站點(diǎn)的逐日觀測(cè)表常見(jiàn)公開(kāi)來(lái)源有國(guó)家級(jí)氣象站歷史觀測(cè)數(shù)據(jù)共享服務(wù)、氣象數(shù)據(jù)網(wǎng)站以及 NASA POWER 這類(lèi)再分析數(shù)據(jù)集。不管從哪個(gè)渠道拿落到 csv 或 excel 之后字段大同小異下表是這套資源里保留的核心字段字段含義單位連續(xù)性date觀測(cè)日期-離散tmax日最高氣溫℃連續(xù)tmin日最低氣溫℃連續(xù)temp日平均氣溫℃連續(xù)precip日降水量mm連續(xù)大量 0 值humidity日均相對(duì)濕度%連續(xù)wind日均風(fēng)速m/s連續(xù)sun日照時(shí)數(shù)h連續(xù)pressure日均氣壓hPa連續(xù)字段選擇上有個(gè)常見(jiàn)做法初版分析只保留數(shù)值連續(xù)性好的列天氣現(xiàn)象、云量這類(lèi)文本或分類(lèi)字段留到后面做專(zhuān)項(xiàng)分析不要一上來(lái)全塞進(jìn)統(tǒng)計(jì)里。我一般會(huì)把 date 設(shè)成唯一索引其余列統(tǒng)一轉(zhuǎn)成 float先跑一遍 dtypes 檢查省得后面在類(lèi)型問(wèn)題上翻車(chē)。2.2 用 pandas 加載數(shù)據(jù)并做缺失值畫(huà)像先用 pandas 把數(shù)據(jù)讀進(jìn)來(lái)同時(shí)把日期拆成年、月兩列這兩列是所有分組統(tǒng)計(jì)的前提。import pandas as pd df pd.read_csv( weather_daily.csv, parse_dates[date], # 把 date 解析成 datetime date_format%Y-%m-%d, # 顯式指定格式避免解析失敗 ) df df.set_index(date) # 日期設(shè)為行索引 df[year] df.index.year # 拆出年份 df[month] df.index.month # 拆出月份 missing df.isna().sum() print(各列缺失值數(shù)量) print(missing[missing 0]) print(f總行數(shù){len(df)})這段代碼做了三件事parse_dates 把日期解析成 pandas 的 datetime 類(lèi)型配合 date_format 顯式指定格式可以避免默認(rèn)解析器遇到混合格式時(shí)整列回退成字符串set_index 讓日期成為行索引后面按年按月切片都依賴(lài)它isna().sum() 輸出每列缺失值數(shù)量先給數(shù)據(jù)畫(huà)個(gè)像。有一點(diǎn)要注意date_format 是 pandas 2.0 以后的寫(xiě)法老版本里這個(gè)參數(shù)叫 format寫(xiě)腳本前先確認(rèn)環(huán)境版本。拿到缺失畫(huà)像之后要區(qū)分三類(lèi)缺失單點(diǎn)缺失、連續(xù)缺失、整月缺失處理策略完全不同。單點(diǎn)缺失可以用鄰近值插補(bǔ)連續(xù)缺失超過(guò)一周就不要再插值了插出來(lái)的平滑曲線是假數(shù)據(jù)整月缺失只能標(biāo)記任何填充都是在編造。下面是一個(gè)按年按月分組填充氣溫缺失值的寫(xiě)法# 按年月分組組內(nèi)均值填充缺失 df[tmax] df.groupby([year, month])[tmax].transform( lambda x: x.fillna(x.mean()) )groupby 按年和月分組后transform 會(huì)把填充結(jié)果按原索引對(duì)齊回每一行表結(jié)構(gòu)不變。lambda 里的 fillna(x.mean()) 只填充當(dāng)前組內(nèi)部的均值避免用全年均值把冬季缺口填成夏季水平。這里有個(gè)容易忽略的細(xì)節(jié)如果整組缺失組內(nèi)均值本來(lái)就是 NaNtransform 之后仍然返回 NaN。我的習(xí)慣是填充完再跑一次 isna().sum()把殘余 NaN 數(shù)量寫(xiě)進(jìn)報(bào)告的數(shù)據(jù)質(zhì)量說(shuō)明里。2.3 異常值識(shí)別物理邊界與分位數(shù)雙保險(xiǎn)清洗的第三件事是處理異常值。氣象數(shù)據(jù)有天然優(yōu)勢(shì)物理邊界非常清楚。比如某站歷史極端最高溫 42℃突然出現(xiàn)一條 58℃基本可以判定是傳感器或錄入錯(cuò)誤。我一般用兩道檢查物理邊界直接標(biāo)記分位數(shù)檢查看分布尾部。cols [tmax, tmin, temp, precip] for col in cols: q01 df[col].quantile(0.01) q99 df[col].quantile(0.99) print(f{col}: 1%分位數(shù){q01:.1f}, 99%分位數(shù){q99:.1f})quantile(0.01) 和 quantile(0.99) 給出分布兩端的參考值超過(guò) 99% 分位數(shù)的記錄并不一定錯(cuò)誤極端高溫本身就是研究對(duì)象的一部分所以策略是只標(biāo)記、不刪除。我會(huì)把可疑行導(dǎo)出成單獨(dú)文件在報(bào)告實(shí)驗(yàn)里寫(xiě)清楚人工核驗(yàn)結(jié)果。記住一條在氣象分析里刪除是最后手段先標(biāo)記、再核驗(yàn)、再?zèng)Q定這個(gè)順序能幫你躲過(guò)大部分?jǐn)?shù)據(jù)質(zhì)量事故。提示所有統(tǒng)計(jì)輸出在寫(xiě)報(bào)告時(shí)都要保留一份原始導(dǎo)出文件數(shù)據(jù)質(zhì)量說(shuō)明應(yīng)該是報(bào)告的第一節(jié)別跳過(guò)。3. 探索性分析分布、周期與相關(guān)檢驗(yàn)怎么選方法數(shù)據(jù)洗干凈之后進(jìn)入探索性分析階段。這一章對(duì)應(yīng)數(shù)據(jù)分析的方法里最核心的三板斧描述分布、拆解周期、檢驗(yàn)相關(guān)。氣象分析報(bào)告實(shí)驗(yàn)的主體內(nèi)容也全集中在這塊。3.1 描述性統(tǒng)計(jì)與分布形態(tài)檢查先看整體統(tǒng)計(jì)量。pandas 的 describe 是第一個(gè)必跑的檢查但只看默認(rèn)輸出不夠要補(bǔ)偏度。cols [tmax, tmin, temp, precip, humidity, wind, sun] desc df[cols].describe().T # 轉(zhuǎn)置成變量行為讀數(shù) desc[skew] df[cols].skew() # 追加偏度列 print(desc.round(2)).T 把變量轉(zhuǎn)成行、統(tǒng)計(jì)量轉(zhuǎn)成列這樣逐行可讀skew() 計(jì)算偏度。降水列的偏度會(huì)遠(yuǎn)大于 0因?yàn)榇蠖鄶?shù)日子降水為 0 或很小偶爾幾天暴雨把分布拉成右偏風(fēng)速一般輕微右偏氣溫的偏度接近 0??吹狡却蟮牧泻罄m(xù)相關(guān)分析要優(yōu)先選 Spearman 而不是 Pearson這個(gè)判斷在 3.3 會(huì)用到。分布檢查還可以配合直方圖看形態(tài)import matplotlib.pyplot as plt fig, axes plt.subplots(1, 3, figsize(14, 4)) for ax, col in zip(axes, [temp, precip, wind]): ax.hist(df[col].dropna(), bins40) # 40 組直方圖 ax.set_title(col) plt.tight_layout() plt.show()bins40 是經(jīng)驗(yàn)參數(shù)幾千行數(shù)據(jù)用 40 組能把分布形狀顯示清楚太少會(huì)丟掉細(xì)節(jié)太多會(huì)抖動(dòng)。觀察重點(diǎn)氣溫接近單峰對(duì)稱(chēng)分布降水是右偏尖峰風(fēng)速中度右偏。這些形態(tài)判斷會(huì)直接決定后面選什么統(tǒng)計(jì)方法、怎么解讀相關(guān)系數(shù)別把直方圖當(dāng)成湊數(shù)的配圖。3.2 季節(jié)周期分析按月聚合與箱線圖氣象數(shù)據(jù)季節(jié)周期天然存在不拆開(kāi)看等于浪費(fèi)數(shù)據(jù)里最重要的信息。先按月份聚合看均值曲線再看箱線圖判斷每月離散度。monthly df.groupby(month)[temp].agg([mean, std, count]) print(monthly.round(2)) # 按月份繪制箱線圖觀察季節(jié)分布 df[temp].plot(kindbox, bydf[month], figsize(10, 5))agg 一次算出月度均值、標(biāo)準(zhǔn)差和樣本量count 順便檢查每月樣本量是否穩(wěn)定。箱線圖橫軸按月份排列夏季箱體整體上移、冬季下移季節(jié)規(guī)律一目了然。如果某個(gè)月份箱體異常寬說(shuō)明該月方差偏大站點(diǎn)可能經(jīng)歷過(guò)搬遷或儀器更換這些背景信息要在報(bào)告里交代否則讀者會(huì)對(duì)離群月份產(chǎn)生困惑。如果數(shù)據(jù)跨多個(gè)年份我還建議做一次季節(jié)分解把趨勢(shì)項(xiàng)、季節(jié)項(xiàng)、殘差項(xiàng)拆開(kāi)看。statsmodels 的 seasonal_decompose 是現(xiàn)成工具from statsmodels.tsa.seasonal import seasonal_decompose # 逐日數(shù)據(jù)聚合到月度均值 series df[temp].resample(ME).mean().dropna() result seasonal_decompose(series, modeladditive, period12) result.trend.plot() # 趨勢(shì)項(xiàng) result.seasonal.plot() # 季節(jié)項(xiàng)resample(ME) 把逐日數(shù)據(jù)聚合到月度均值注意新版 pandas 里 ME 是標(biāo)準(zhǔn)寫(xiě)法老版本寫(xiě) M 也認(rèn)。period12 代表 12 個(gè)月一個(gè)循環(huán)model 參數(shù)選 additive 還是 multiplicative取決于季節(jié)波動(dòng)的幅度是否隨水平變化氣溫一般加性夠用降水用乘法更貼近實(shí)際。分解出來(lái)的 trend 項(xiàng)就是做長(zhǎng)期趨勢(shì)判斷的干凈素材直接看原始年均值曲線反而會(huì)被季節(jié)波動(dòng)干擾。3.3 變量相關(guān)分析為什么優(yōu)先選 Spearman氣象分析報(bào)告里最有價(jià)值的結(jié)論往往是變量之間的關(guān)系氣溫和濕度、氣溫和降水、風(fēng)速和氣壓。計(jì)算相關(guān)矩陣時(shí)方法選擇直接影響結(jié)論方向。import scipy.stats as stats cols [tmax, precip, humidity, wind] pearson df[cols].corr(methodpearson) spearman df[cols].corr(methodspearman) print(Pearson 相關(guān)) print(pearson.round(2)) print(Spearman 相關(guān)) print(spearman.round(2))method 參數(shù)是關(guān)鍵Pearson 衡量線性相關(guān)對(duì)離群點(diǎn)和偏態(tài)分布敏感Spearman 基于秩次只關(guān)心單調(diào)關(guān)系對(duì)降水這種右偏分布穩(wěn)健得多。實(shí)踐里我兩個(gè)都算如果兩者差異明顯比如 Pearson 接近 0 而 Spearman 不為 0說(shuō)明變量之間是非線性關(guān)系報(bào)告里要專(zhuān)門(mén)討論不能只挑好看的那個(gè)寫(xiě)。單條相關(guān)系數(shù)的顯著性檢驗(yàn)同樣要走r, p stats.spearmanr(df[temp], df[humidity]) print(f溫度-濕度: r{r:.3f}, p{p:.4f})spearmanr 返回相關(guān)系數(shù)和 p 值p 小于 0.05 才算顯著相關(guān)。但氣象數(shù)據(jù)樣本量動(dòng)不動(dòng)幾千條微小的相關(guān)系數(shù)也會(huì)被檢驗(yàn)成顯著所以報(bào)告里必須強(qiáng)調(diào)r 的絕對(duì)值小于 0.2 時(shí)統(tǒng)計(jì)顯著不等于實(shí)際有意義解釋力非常有限。這一條是新手寫(xiě)分析報(bào)告最容易犯的過(guò)度解讀錯(cuò)誤寧可寫(xiě)得保守也不要吹過(guò)頭。4. 可視化與報(bào)告實(shí)驗(yàn)Python 出圖與結(jié)果落地的配合python數(shù)據(jù)分析與可視化是這套實(shí)踐包里觀感最直接的部分。統(tǒng)計(jì)數(shù)字很難讓讀者直接信服一張趨勢(shì)圖加一張相關(guān)熱力圖報(bào)告的說(shuō)服力立刻上一個(gè)臺(tái)階。資源里所有出圖腳本都集中在 analysis_plots.py改參數(shù)就可以復(fù)用到別的站點(diǎn)數(shù)據(jù)。4.1 溫度趨勢(shì)圖年際曲線與月度季節(jié)曲線先畫(huà)兩幅最有代表性的圖年均氣溫曲線和月度平均曲線分別回答長(zhǎng)期怎么變、年內(nèi)怎么波動(dòng)。import matplotlib.pyplot as plt yearly df.groupby(year)[temp].mean() # 年均氣溫 monthly df.groupby(month)[temp].mean() # 月均氣溫 fig, (ax1, ax2) plt.subplots(2, 1, figsize(11, 7)) ax1.plot(yearly.index, yearly.values, color#2c7fb8, linewidth1.5) ax1.set_ylabel(年均氣溫 (℃)) ax1.set_title(站點(diǎn)年均氣溫年際變化) ax2.plot(monthly.index, monthly.values, markero, color#f03b20) ax2.set_ylabel(月均氣溫 (℃)) ax2.set_xticks(range(1, 13)) # 強(qiáng)制顯示 1 到 12 月 ax2.set_title(年內(nèi)月均氣溫季節(jié)曲線) plt.tight_layout() plt.savefig(temperature_trend.png, dpi150)subplots(2, 1) 生成上下兩張子圖返回的 axes 對(duì)象按順序給 ax1、ax2 使用。savefig 的 dpi150 是報(bào)告貼圖的最低要求要提交印刷版再提到 300。ax2.set_xticks(range(1, 13)) 這行容易被漏掉不設(shè)置的話 pandas 會(huì)按數(shù)據(jù)自動(dòng)挑刻度可能跳過(guò) 11 月、12 月橫軸看起來(lái)就是缺的。以降水量為例再畫(huà)一張年累計(jì)降水柱狀圖考察降水的年際波動(dòng)yearly_precip df.groupby(year)[precip].sum() # 每年降水總量 yearly_precip.plot(kindbar, figsize(11, 4), color#3182bd) plt.ylabel(年降水量 (mm)) plt.savefig(precip_yearly.png, dpi150)groupby(year)[precip].sum() 匯總每年降水總量bar 圖適合展示離散年份的對(duì)比。注意降水柱狀圖容易出現(xiàn)個(gè)別年份明顯偏高或偏低這可能是真實(shí)的旱澇差異也可能是缺測(cè)導(dǎo)致的系統(tǒng)性低估所以畫(huà)完要回頭對(duì)照第 2 章的數(shù)據(jù)質(zhì)量說(shuō)明核對(duì)一遍別直接把圖扔進(jìn)報(bào)告。4.2 相關(guān)矩陣熱力圖一眼看清變量關(guān)系相關(guān)矩陣用 seaborn 熱力圖展示是報(bào)告里信息密度最高的一張圖通常放在分析章節(jié)的開(kāi)頭位置。import seaborn as sns corr df[[tmax, tmin, precip, humidity, wind, sun]].corr( methodspearman # 用 Spearman原因見(jiàn) 3.3 ) plt.figure(figsize(8, 6)) sns.heatmap( corr, annotTrue, # 格子里顯示數(shù)值 fmt.2f, # 保留兩位小數(shù) cmapRdBu_r, # 紅正藍(lán)負(fù) vmin-1, vmax1, center0, # 0 值顯示為白色 ) plt.tight_layout() plt.savefig(corr_heatmap.png, dpi150)annotTrue 把相關(guān)系數(shù)直接寫(xiě)在格子里fmt.2f 控制顯示格式cmapRdBu_r 讓正相關(guān)呈紅色、負(fù)相關(guān)呈藍(lán)色這是氣象報(bào)告里的慣用配色紅藍(lán)相反不會(huì)引起歧義center0 保證 0 值是白色冷暖對(duì)稱(chēng)看起來(lái)不會(huì)誤解方向。注意這里的相關(guān)矩陣用的是 Spearman原因上一章說(shuō)過(guò)——降水偏態(tài)嚴(yán)重Pearson 會(huì)給出誤導(dǎo)性數(shù)值出圖前別改回默認(rèn)。4.3 報(bào)告實(shí)驗(yàn)的輸出組織數(shù)據(jù)、圖表、結(jié)論三件套報(bào)告實(shí)驗(yàn)要的不只是一張圖而是一套能復(fù)現(xiàn)的記錄。我習(xí)慣把所有實(shí)驗(yàn)結(jié)果導(dǎo)出成 csv 和圖片再按模板寫(xiě)數(shù)據(jù)分析報(bào)告每個(gè)結(jié)論都能對(duì)應(yīng)到具體輸出文件。summary df.groupby(month).agg( temp_mean(temp, mean), # 月度均溫 temp_std(temp, std), # 月度標(biāo)準(zhǔn)差 precip_sum(precip, sum), # 月度降水總量 ).round(2) summary.to_csv(analysis_results.csv, encodingutf-8-sig) final_corr df[[tmax, precip, humidity]].corr( methodspearman ).round(3) final_corr.to_csv(correlation_results.csv, encodingutf-8-sig)agg 用元組語(yǔ)法給每個(gè)輸出列指定聚合函數(shù)輸出列名直接叫 temp_mean、temp_std比 pandas 默認(rèn)的列名可讀性好很多。to_csv 里的 encodingutf-8-sig 是關(guān)鍵參數(shù)Windows 上 Excel 打開(kāi)帶 BOM 的 utf-8 文件才不會(huì)中文亂碼這是報(bào)告交付環(huán)節(jié)最常見(jiàn)的坑。實(shí)驗(yàn)記錄的思路是每個(gè)輸出對(duì)應(yīng)報(bào)告的一節(jié)描述統(tǒng)計(jì)支撐數(shù)據(jù)概況相關(guān)矩陣支撐變量關(guān)系討論趨勢(shì)圖支撐長(zhǎng)期變化結(jié)論三件套齊了報(bào)告實(shí)驗(yàn)才算閉環(huán)。5. 避坑與排查氣象數(shù)據(jù)分析的五個(gè)翻車(chē)現(xiàn)場(chǎng)這一章把氣象數(shù)據(jù)分析項(xiàng)目實(shí)踐里最容易踩的坑集中列出來(lái)。每一條都是真實(shí)發(fā)生過(guò)的翻車(chē)現(xiàn)場(chǎng)按現(xiàn)象、原因、解決的順序?qū)懻罩挪槟苁∠麓罅糠倒r(shí)間。5.1 日期解析失敗讀進(jìn)來(lái)全是字符串現(xiàn)象print(df.dtypes) 顯示 date 列是 object 而不是 datetime按年份分組時(shí)報(bào)錯(cuò)或者分組結(jié)果完全對(duì)不上。原因csv 文件里的日期格式不標(biāo)準(zhǔn)2023/1/5 和 2023-01-05 混著寫(xiě)或者月份用了英文縮寫(xiě)pandas 默認(rèn)解析器遇到無(wú)法解析的格式整列回退成字符串。解決讀取時(shí)顯式指定格式用 date_format 參數(shù)強(qiáng)制解析規(guī)則。不確定文件里是什么格式時(shí)先讀前幾行看原始字符串再下手別靠猜。df pd.read_csv( weather_daily.csv, parse_dates[date], date_format%Y-%m-%d, # 格式與文件實(shí)際保持一致 )這個(gè)坑幾乎每個(gè)做氣象數(shù)據(jù)分析的人都會(huì)碰一次排查成本其實(shí)很低就是多寫(xiě)一個(gè)參數(shù)的事但漏了它后面所有時(shí)間序列操作都白搭。5.2 缺失值填充把冬季均值拉高現(xiàn)象補(bǔ)完缺失之后冬季平均氣溫比歷史記錄明顯偏高1 月均值異常離譜。原因用了全局均值填充所有月份的缺失值。冬季本來(lái)偏冷夏季均值混進(jìn)去之后冬季的缺口被填成偏高數(shù)值季節(jié)特征被徹底破壞。解決按年按月分組填充或者用相鄰日期線性插值。分組填充 2.2 里寫(xiě)過(guò)這里補(bǔ)插值寫(xiě)法df[tmin] df[tmin].interpolate( methodlinear, limit_directionboth, # 首尾缺失也向外推 )interpolate 對(duì)連續(xù)幾天缺失效果好limit_directionboth 表示序列首尾的缺失也向前后外推。但注意如果某個(gè)月整月缺失插值會(huì)把邊界連成直線看著平滑實(shí)際是編造的假數(shù)據(jù)必須識(shí)別出來(lái)并在報(bào)告里聲明不能當(dāng)真實(shí)觀測(cè)用。5.3 降水字段的 0 與 NaN 混為一談現(xiàn)象降水量為 0 的天數(shù)統(tǒng)計(jì)出來(lái)特別少或者年降水總量算出來(lái)明顯偏低。原因氣象記錄里無(wú)降水記 0缺測(cè)記 NaN兩者含義完全不同。有人清洗時(shí)用 dropna() 把 NaN 行整行刪掉0 值保留結(jié)果樣本缺失集中在無(wú)降水日上年降水總量被系統(tǒng)性低估。解決先把 0 和 NaN 分開(kāi)統(tǒng)計(jì)再?zèng)Q定策略。降水缺失不做均值填充用前向填充或者直接標(biāo)記因?yàn)榫堤畛鋾?huì)憑空造出毛毛雨記錄。rain_na df[precip].isna().sum() rain_zero (df[precip] 0).sum() print(f缺測(cè){rain_na} 天無(wú)降水{rain_zero} 天)這個(gè)統(tǒng)計(jì)必須寫(xiě)進(jìn)報(bào)告實(shí)驗(yàn)的數(shù)據(jù)質(zhì)量說(shuō)明里它有實(shí)際業(yè)務(wù)含義缺測(cè)比例高說(shuō)明站點(diǎn)維護(hù)差后續(xù)趨勢(shì)分析的可信度要打折讀者一眼就能看出數(shù)據(jù)的底線在哪。5.4 相關(guān)矩陣出現(xiàn)違背常識(shí)的正負(fù)號(hào)現(xiàn)象氣溫與降水的相關(guān)系數(shù)算出來(lái)是正的數(shù)值還不小和夏季多雨、冬季干燥的常識(shí)完全對(duì)不上。原因計(jì)算相關(guān)時(shí)沒(méi)有去掉季節(jié)效應(yīng)。把 1 月到 12 月混在一起算溫度高的月份降水也多整體看就是正相關(guān)但這種相關(guān)其實(shí)是季節(jié)混疊造成的假象不是氣象學(xué)意義上的真實(shí)關(guān)系。解決分季節(jié)計(jì)算寫(xiě)進(jìn)報(bào)告更直觀for season, months in [(春, [3, 4, 5]), (夏, [6, 7, 8]), (秋, [9, 10, 11]), (冬, [12, 1, 2])]: sub df[df[month].isin(months)] r, p stats.spearmanr(sub[temp], sub[precip]) print(f{season}: r{r:.2f}, p{p:.3f})這個(gè)翻車(chē)點(diǎn)特別適合寫(xiě)進(jìn)報(bào)告實(shí)驗(yàn)的討論部分先說(shuō)明整體相關(guān)受季節(jié)干擾再展示分季節(jié)結(jié)果分析深度立刻不一樣評(píng)審一眼就能看出你真正理解數(shù)據(jù)。5.5 圖表中文全部顯示成方塊現(xiàn)象圖表標(biāo)題和圖例里的中文變成空心方塊英文和數(shù)字正常。原因matplotlib 默認(rèn)字體 DejaVu Sans 不包含中文字形Windows 和 Linux 上默認(rèn)配置都不帶中文字體支持。解決繪圖前統(tǒng)一設(shè)置中文字體Windows 常用 SimHeiLinux 用 Noto Sans CJK SC。import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, Noto Sans CJK SC] plt.rcParams[axes.unicode_minus] False # 修負(fù)號(hào)方塊axes.unicode_minus 設(shè)為 False 解決坐標(biāo)軸負(fù)號(hào)顯示成方塊的問(wèn)題。這段配置建議放在腳本最開(kāi)頭統(tǒng)一設(shè)置不要每張圖調(diào)一次也別指望每臺(tái)機(jī)器字體都一樣多列幾個(gè)候選字體名是穩(wěn)妥做法。6. 進(jìn)階用法滑動(dòng)平均與線性回歸交叉驗(yàn)證趨勢(shì)前面把探索分析和出圖都跑通了最后這一步是把結(jié)論驗(yàn)證做扎實(shí)年均氣溫到底有沒(méi)有上升趨勢(shì)只用均值曲線肉眼判斷不夠客觀我的做法是兩條腿走路先做 12 個(gè)月滑動(dòng)平均去除季節(jié)波動(dòng)再用線性回歸估計(jì)趨勢(shì)斜率。# 月度序列 12 個(gè)月滑動(dòng)平均 monthly df[temp].resample(ME).mean().to_frame() monthly[temp_ma] monthly[temp].rolling( window12, # 12 個(gè)月窗口 centerTrue # 窗口對(duì)齊到中間點(diǎn) ).mean() print(monthly[temp_ma].tail())rolling(window12) 對(duì)月度序列做 12 個(gè)月滑動(dòng)平均centerTrue 讓窗口對(duì)齊到中心曲線比原始數(shù)據(jù)平滑且沒(méi)有相位偏移。滑動(dòng)平均把季節(jié)周期抹掉之后剩下的主要是年際波動(dòng)看趨勢(shì)比直接看逐年線干凈得多這也是氣象分析里最常用的平滑方式?;貧w部分只取近 20 年數(shù)據(jù)這個(gè)窗口長(zhǎng)度在氣象分析里比較常用太短容易被單一年份極端天氣帶偏太長(zhǎng)又混進(jìn)多年代際震蕩。yearly df.groupby(year)[temp].mean() slope, intercept, r_value, p_value, std_err stats.linregress( yearly.index.astype(int), yearly.values, ) print(f趨勢(shì)斜率{slope:.4f} ℃/年, R2{r_value**2:.3f}, p{p:.3f})linregress 返回斜率、截距、相關(guān)系數(shù)、p 值和標(biāo)準(zhǔn)誤五個(gè)值這套輸出足夠支撐報(bào)告里的趨勢(shì)判斷。兩個(gè)細(xì)節(jié)必須強(qiáng)調(diào)第一滑動(dòng)平均后的序列存在自相關(guān)回歸得到的 p 值會(huì)偏樂(lè)觀嚴(yán)謹(jǐn)一點(diǎn)需要做塊自舉或 HAC 標(biāo)準(zhǔn)誤校正第二斜率單位是 ℃/年寫(xiě)報(bào)告時(shí)要換算成每十年變化量讀者才直觀。氣象分析報(bào)告實(shí)驗(yàn)做到這一步已經(jīng)比大多數(shù)課程作業(yè)多了一個(gè)層次不滿(mǎn)足于畫(huà)出趨勢(shì)而是對(duì)趨勢(shì)做顯著性檢驗(yàn)。從那以后我每次跑氣象數(shù)據(jù)分析都會(huì)強(qiáng)制走一遍交叉驗(yàn)證流程先畫(huà)原始圖再滑動(dòng)平均最后回歸出斜率三個(gè)結(jié)果對(duì)不上就回頭查數(shù)據(jù)。做數(shù)據(jù)分析最怕結(jié)論只來(lái)自一張圖、一個(gè)數(shù)字沒(méi)有第二重驗(yàn)證兜底。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取