實戰(zhàn):用 Pandas 完成 COVID-19 疫情建模與論文共現(xiàn)分析)
Data-Science-For-Beginners 課 07 作業(yè)實戰(zhàn)用 Pandas 完成 COVID-19 疫情建模與論文共現(xiàn)分析【免費下載鏈接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!項目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners本篇實戰(zhàn)指南以本倉庫 2-Working-With-Data/07-python/assignment.md 的課后作業(yè)為骨架面向已經(jīng)學完 Python 與 Pandas 課程 的讀者。你將基于課內(nèi)兩個挑戰(zhàn)COVID-19 疫情傳播建模、COVID-19 學術論文文本分析中已寫好的代碼繼續(xù)深化完成多國R_t對比、死亡/康復與感染的相關性、病程時長推斷、死亡率時序變化以及藥物共現(xiàn)矩陣、熱力圖與正則提取劑量的實戰(zhàn)任務。讀完本文你將掌握用 Pandas Matplotlib 處理時間序列與半結構化文本的完整套路并學會把課內(nèi)示例代碼改造成可復用的分析管線。作業(yè)背景與完成標準本作業(yè)要求你在課內(nèi)兩個挑戰(zhàn)的基礎上接著寫而不是從零開始。挑戰(zhàn)代碼分別在 notebook-covidspread.ipynb疫情建模與 notebook-papers.ipynb論文分析中。評分標準Rubric分三檔等級要求優(yōu)秀Exemplary所有任務完成有圖形化展示與文字解釋且至少完成兩個加分目標之一合格Adequate完成超過 5 項任務但未嘗試加分目標或結果不清晰需改進Needs Improvement完成少于 5 項但多于 3 項且可視化無法說明問題從評分標準可以看出任務數(shù)量、可視化質(zhì)量、解釋說明缺一不可加分目標是拉開差距的關鍵。作業(yè)原始數(shù)據(jù)說明與評分細則詳見 translations/bg/2-Working-With-Data/07-python/assignment.md保加利亞語譯本內(nèi)容與英文原版一致。第一部分COVID-19 疫情傳播建模準備數(shù)據(jù)與課內(nèi)代碼回顧疫情數(shù)據(jù)來自約翰霍普金斯大學 CSSE 的時間序列數(shù)據(jù)集本倉庫在 data/COVID/ 下提供了三份快照倉庫內(nèi)共 266 行、150 列覆蓋 188 個國家/地區(qū)日期列從 2020-01-22 起time_series_covid19_confirmed_global.csv累計確診time_series_covid19_recovered_global.csv累計康復time_series_covid19_deaths_global.csv累計死亡notebook 中默認從網(wǎng)絡讀取離線時可改用本地快照只需替換base_url見 notebook-covidspread.ipynb 第 3 個代碼單元base_url ../../data/COVID/ # 離線模式改用倉庫本地快照 # base_url https://raw.githubusercontent.com/... # 在線模式默認 infected pd.read_csv(base_url time_series_covid19_confirmed_global.csv) recovered pd.read_csv(base_url time_series_covid19_recovered_global.csv) deaths pd.read_csv(base_url time_series_covid19_deaths_global.csv)課內(nèi)已經(jīng)完成的預處理鏈路包括按Country/Region用groupby().sum()合并省份行 → 用drop(columns[Lat,Long,Province/State])去掉元數(shù)據(jù)列 → 用mkframe(country)把三份累計數(shù)據(jù)拼成按日期索引的 DataFrame → 用diff()求每日新增、rolling(7).mean()平滑周波動。此外人口數(shù)據(jù)來自 data/UID_ISO_FIPS_LookUp_Table.csv用于計算每百萬人感染率pinfected。R_t的核心公式8 天滑動窗口在 notebook 中實現(xiàn)為df[Rt] df[ninfected].rolling(8).apply(lambda x: x[4:].sum()/x[:4].sum())其數(shù)學含義是第t天的基本再生數(shù)近似等于窗口內(nèi)后半段新增感染數(shù)之和除以前半段之和即R_t (I_{t-7}I_{t-6}I_{t-5}I_{t-4}) / (I_{t-3}I_{t-2}I_{t-1}I_t)其中I_t為第t天新增感染人數(shù)。R_t 1表示疫情仍在擴散R_t 1表示傳播在收斂。畫圖前需把除零產(chǎn)生的inf替換為NaN再用fillna(methodpad)前向填充否則曲線會出現(xiàn)斷口ax df[df.index 2020-05-01][Rt].replace(np.inf, np.nan).fillna(methodpad).plot(figsize(10,3)) ax.set_ylim([0,6]) # 限制縱軸以看清早期波動 ax.axhline(1, linestyle--, colorred) # R_t1 參考線 plt.show()任務一多國 R_t 對比圖把課內(nèi)的單國邏輯封裝成函數(shù)返回某國的R_t序列再對 56 個國家統(tǒng)一繪圖def compute_rt(country, window8, half4): df mkframe(country) df[ninfected] df[infected].diff() rt df[ninfected].rolling(window).apply( lambda x: x[half:].sum()/x[:half].sum(), rawTrue) return rt.replace(np.inf, np.nan).fillna(methodpad) countries [US, United Kingdom, Italy, Brazil, India, Japan] rt_series {c: compute_rt(c) for c in countries} # 方案 A單圖疊加比較 ax pd.DataFrame(rt_series).plot(figsize(12, 4)) ax.set_ylabel(R_t); ax.axhline(1, linestyle--, colorred) # 方案 B并排多子圖適合各國波峰錯峰明顯的場景 fig, axes plt.subplots(2, 3, figsize(12, 6), shareyTrue) for ax, c in zip(axes.flat, countries): rt_series[c].plot(axax, titlec) ax.axhline(1, linestyle--, colorred, lw0.8) plt.tight_layout()實現(xiàn)要點rawTrue讓apply直接傳入 ndarray 而非 Series可顯著加速滑動窗口計算各國疫情階段不同疊加圖適合看誰先起峰、誰先收斂子圖適合逐國觀察R_t是否持續(xù)高于 1。任務二死亡數(shù)、康復數(shù)與感染數(shù)的相關性用mkframe拿到累計值后直接調(diào)用 Pandas 內(nèi)置的相關系數(shù)并結合散點圖觀察滯后關系df mkframe(US) corr df[[infected, recovered, deaths]].corr() print(corr) # 平滑后更能反映趨勢相關性 smooth df[[infected, recovered, deaths]].rolling(7).mean() smooth.plot.scatter(xinfected, ydeaths)可以預期感染數(shù)與死亡數(shù)高度正相關但死亡往往滯后于感染若干天存在病程時滯。一個值得探索的分析是計算每日新增死亡與每日新增感染在不同時間滯后 k 天下的相關系數(shù)找出相關系數(shù)最大時的 k這為任務三的病程推斷提供定量依據(jù)new_inf df[infected].diff().rolling(7).mean() new_deaths df[deaths].diff().rolling(7).mean() lags {} for k in range(0, 40): lags[k] new_deaths.corr(new_inf.shift(k)) best_k max(lags, keylags.get)任務三推斷典型病程時長思路是以視覺方式關聯(lián)感染率與死亡率曲線并尋找異常。把兩條曲線放到同一張圖上觀察死亡曲線相對感染曲線的時間偏移df[ninfected] df[infected].diff().rolling(7).mean() df[ndeaths] df[deaths].diff().rolling(7).mean() # 歸一化到 [0,1] 便于疊加比較形狀 ax (df[ninfected]/df[ninfected].max()).plot(labelnew infected (norm)) (df[ndeaths]/df[ndeaths].max()).shift(0).plot(axax, labelnew deaths (norm)) ax.legend()實際操作上可以遍歷滯后天數(shù) k把ndeaths.shift(k)與ninfected疊加找到兩條曲線峰對峰最吻合的 k即為粗略病程時長。注意不同國家因檢測策略、死亡報告口徑不同推斷出的滯后可能不一致這正是作業(yè)要求多看幾個國家的原因——異常點如某國死亡率曲線突然偏離往往對應數(shù)據(jù)質(zhì)量或政策干預如封城、檢測量變化事件。任務四死亡率及其隨時間的變化基本定義fatality rate deaths / infected * 100。作業(yè)的提示非常關鍵要考慮病程天數(shù)先平移一條時間序列再做計算。原因在于當天確診的人不會當天死亡直接用同日累計值會低估早期真實病死率df mkframe(US) df[fatality] df[deaths] / df[infected] * 100 df[fatality].plot() # 樸素計算早期明顯偏低 # 平移改進假設病程 D 天將感染序列后移 D 天再相除 D 14 # 可由任務三得到的滯后天數(shù)替換 df[fatality_shifted] df[deaths].shift(-D) / df[infected] * 100 df[[fatality, fatality_shifted]].plot()同時建議平滑rolling(7).mean()去除報告導致的周波動并觀察死亡率隨時間是否趨穩(wěn)——這能反映醫(yī)療資源擠兌、治療手段改進或檢測范圍擴大等動態(tài)因素。第二部分COVID-19 論文分析數(shù)據(jù)集說明與課內(nèi)代碼回顧本挑戰(zhàn)使用 CORD-19 論文數(shù)據(jù)集倉庫不隨附需自行下載metadata.csv大小約 1 GB。課內(nèi) notebook notebook-papers.ipynb 已完成如下分析鏈路讀取metadata.csv把publish_time轉成datetime并畫直方圖手工維護藥物清單medicationshydroxychloroquine、chloroquine、tocilizumab、remdesivir、azithromycin、lopinavir、ritonavir、dexamethasone、heparin、favipiravir、methylprednisolone與診斷清單diagnosiscovid、sars、pneumonia、infection、diabetes、coronavirus、death用df[m] df[abstract].apply(lambda x: str(x).lower().count( m))逐詞計數(shù)注意詞首加空格避免chloroquine被hydroxychloroquine內(nèi)的子串污染按年-月分組groupby([index.year, index.month]).sum()得到治療策略月度趨勢用np.zeros((len(medications), len(diagnosis)))構建藥物×診斷共現(xiàn)矩陣逐篇摘要累加用plt.imshow(..., cmaphot)畫熱力圖并用 Plotly 的go.Sankey畫桑基圖notebook 中封裝為sankey(cat1, cat2, m, treshold0, h1[], h2[])函數(shù)。任務一構建藥物共現(xiàn)矩陣把課內(nèi)藥物×診斷的代碼改造成藥物×藥物遍歷每篇摘要只要某兩種藥物在同一摘要中出現(xiàn)就計數(shù)一次meds medications # 沿用課內(nèi) 11 種藥物清單 coocc np.zeros((len(meds), len(meds)), dtypeint) for a in df[abstract]: x str(a).lower() present [m for m in meds if m in x] for i in range(len(present)): for j in range(i1, len(present)): coocc[meds.index(present[i]), meds.index(present[j])] 1 coocc[meds.index(present[j]), meds.index(present[i])] 1 # 對稱 cooc_df pd.DataFrame(coocc, indexmeds, columnsmeds)出于效率考慮也可以先構造布爾矩陣再與自身轉置做矩陣乘法present pd.DataFrame({m: df[abstract].str.contains( m, caseFalse) for m in meds})然后coocc present.T present注意此時對角線為各藥物總出現(xiàn)次數(shù)。觀察重點哪些藥物常在同一篇論文里成對出現(xiàn)例如 chloroquine 與 azithromycin、lopinavir 與 ritonavir 常作為聯(lián)合用藥方案被共同研究。任務二熱力圖可視化共現(xiàn)矩陣用 Matplotlib 畫出共現(xiàn)矩陣熱力圖fig, ax plt.subplots(figsize(8, 6)) im ax.imshow(coocc, interpolationnearest, cmaphot) ax.set_xticks(range(len(meds))); ax.set_xticklabels(meds, rotation90) ax.set_yticks(range(len(meds))); ax.set_yticklabels(meds) plt.colorbar(im, axax) plt.show()熱力圖中亮色格高共現(xiàn)次數(shù)即聯(lián)合用藥研究熱點。若矩陣數(shù)值跨度大可先取np.log1p(coocc)再畫壓低少數(shù)極高值對色標的壓縮效應也可疊加數(shù)值標注ax.text(j, i, coocc[i,j])提升可讀性。注意課內(nèi)藥物×診斷熱力圖樣式covidtreat.png 為治療策略堆疊面積圖熱力圖繪制邏輯見 notebook 第 26 個代碼單元可直接遷移復用。加分目標一chord 弦圖可視化共現(xiàn)作業(yè)推薦的第三方庫是chordPyPI 包名。用法示意from chord import Chord # 傳入對稱矩陣與標簽列表矩陣元素為整數(shù)頻次 Chord(coocc.tolist(), meds).to_html() # 生成可交互 HTML若coocc數(shù)值過大可先二值化或按閾值截斷只保留共現(xiàn)次數(shù)高于閾值的藥物對否則弦圖會過于擁擠。按任務說明此目標與另一加分目標完成其一即可達到優(yōu)秀檔。加分目標二用正則表達式提取藥物劑量從take 400mg of chloroquine daily這類句子中抽取劑量如400mg并用 DataFrame 匯總每種藥物出現(xiàn)過的劑量及次數(shù)。關鍵技巧在藥物名周圍限定上下文窗口只統(tǒng)計與藥物名文本距離很近的數(shù)值import re from collections import defaultdict def extract_doses(abstracts, medicine, window30): doses defaultdict(int) pat re.compile(r(\d(?:\.\d)?\s*(?:mg|g|mcg|microgram|gram|milligram)), re.I) for a in abstracts: a str(a).lower() for mm in re.finditer(re.escape(medicine), a): start max(0, mm.start() - window) end min(len(a), mm.end() window) ctx a[start:end] for dm in pat.finditer(ctx): doses[dm.group(1).lower()] 1 return doses rows [] for med in medications: for dose, cnt in extract_doses(df[abstract], med).items(): rows.append({medication: med, dose: dose, count: cnt}) dose_df pd.DataFrame(rows).sort_values([medication, count], ascending[True, False])要點re.escape(medicine)避免藥物名中的特殊字符被當作正則元字符窗口大小此處 30 字符決定文本鄰近的判定范圍劑量模式\d(?:\.\d)?\s*(?:mg|g|...)覆蓋整數(shù)/小數(shù)與常見單位??蛇M一步做單位歸一化如把0.4 g與400 mg視為同一劑量并觀察同一藥物不同劑量隨時間/國別的分布差異。倉庫內(nèi)可深入閱讀的資料課程正文2-Working-With-Data/07-python/README.mdSeries/DataFrame 核心操作、apply/groupby/rolling用法疫情建模完整代碼notebook-covidspread.ipynb論文分析完整代碼notebook-papers.ipynb疫情本地數(shù)據(jù)data/COVID/三份累計時間序列 CSV人口數(shù)據(jù)data/UID_ISO_FIPS_LookUp_Table.csv作業(yè)英文原版2-Working-With-Data/07-python/assignment.md疫情趨勢圖covidspread.png治療策略趨勢圖covidtreat.png課程配套 R 語言版本2-Working-With-Data/07-python/R/供對照學習完成建議按先復現(xiàn)、后改造、再獨立的順序推進先在兩個 notebook 中逐單元運行確認基線輸出再基于本文給出的函數(shù)模板完成四項建模任務與兩項論文分析任務最后任選一個加分目標沖刺優(yōu)秀檔??梢暬瘎毡嘏渖衔淖纸Y論例如某國R_t在何時跌破 1某兩種藥物共現(xiàn)次數(shù)顯著高于其他組合這既是評分標準Exemplary 要求graphically illustrated and explained的要求也是數(shù)據(jù)科學報告的基本素養(yǎng)?!久赓M下載鏈接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!項目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考