ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Data-Science-For-Beginners 第 7 课作业实战:用 Python 完成 COVID-19 疫情传播建模与论文药物共现分析

Data-Science-For-Beginners 第 7 课作业实战:用 Python 完成 COVID-19 疫情传播建模与论文药物共现分析 Data-Science-For-Beginners 第 7 课作业实战用 Python 完成 COVID-19 疫情传播建模与论文药物共现分析【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners本篇文章完整拆解《Data-Science-For-Beginners》课程第 7 课Python 与 Pandas 数据处理的课后作业该作业要求读者在两个官方挑战 Notebook——notebook-covidspread.ipynb疫情传播建模与 notebook-papers.ipynb论文文本分析——的基础上继续深化完成 6 项核心任务与 2 项拓展目标。读完本文你将掌握用 Pandas 处理时间序列滚动窗口、差分、平移对齐、计算再生数 R_t、构建药物共现矩阵并用 heatmap 可视化、以及用正则表达式从医学摘要中抽取药物剂量的完整实战方案。作业原文见 assignment.md英文 与 希腊语译文版即本任务依据的关联文档。作业背景在挑战代码之上做深度数据分析课程第 7 课的核心主张是数据库查询虽然高效但遇到“需要洞察”的场景——分布、相关性、趋势、文本中的隐含信息——用 Python 直接操作数据往往更灵活。课内配套的 README.md 介绍了 Series、DataFrame、groupby、apply、resample等 Pandas 核心概念而作业则要求你把它们真正用起来。作业明确分成两个部分COVID-19 疫情传播建模COVID-19 Spread Modelling基于约翰霍普金斯大学 CSSE 提供的全球疫情时间序列完成 4 项任务COVID-19 论文分析COVID-19 Papers Analysis基于 CORD-19 论文数据集含摘要的metadata.csv完成 2 项任务 2 项拓展目标。作业原文给出的完整任务清单如下第一部分为 5~6 个不同国家绘制R图画在同一张图上对比或用多个图并排展示观察死亡数、康复数与感染数的相关性通过可视化关联感染率与死亡率、寻找异常点推断典型病程持续多久可能需要对比不同国家计算致死率fatality rate及其随时间的变化提示可考虑按病程天数平移某条时间序列后再计算。第二部分构建不同药物的共现矩阵观察哪些药物经常在同一篇摘要中被共同提及可参考“药物×诊断”共现矩阵的构建代码进行修改用 heatmap 可视化该矩阵拓展目标一用 chord diagram弦图可视化药物共现官方提示可参考chord库拓展目标二用正则表达式抽取不同药物的剂量例如从take 400mg of chloroquine daily中抽取400mg并构建展示“不同药物对应不同剂量”的 DataFrame提示考虑药物名附近文本距离内的数值。环境准备与数据获取两个 Notebook 都基于 Python 数据科学生态核心依赖与导入方式在 notebook-covidspread.ipynb 中有明确示例import numpy as np import pandas as pd import matplotlib.pyplot as plt plt.rcParams[figure.figsize] (10, 3) # 放大默认画布便于观察趋势疫情数据的两种获取方式Notebook 默认从约翰霍普金斯大学 CSSE 的 GitHub 仓库在线读取 CSV如果网络不可用仓库本地data/目录下已内置了一份副本可直接切换数据源base_url https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/ # 在线加载 # base_url data/COVID/ # 本地加载仓库 data 目录下的副本 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) countries pd.read_csv(base_url ../UID_ISO_FIPS_LookUp_Table.csv)本地副本对应的文件为 time_series_covid19_confirmed_global.csv、time_series_covid19_deaths_global.csv、time_series_covid19_recovered_global.csv人口数据为 UID_ISO_FIPS_LookUp_Table.csv。从表头可以看到数据的宽表结构每一行是一个国家/省份日期列1/22/20、1/23/20……依次排开。论文数据的获取CORD-19 数据集未包含在仓库内需要自行下载metadata.csv约 1GBNotebook 提示下载可能耗时约 5 分钟。官方 Notebook 给出的加载方式是df pd.read_csv(https://datascience4beginners.blob.core.windows.net/cord/metadata.csv.zip, compressionzip) # df pd.read_csv(metadata.csv) # 若已下载本地文件疫情数据的预处理第一部分的地基Notebook 已经演示了疫情数据从“宽表”到“可分析 DataFrame”的完整预处理链路作业第一部分的所有任务都建立在这套代码之上# 1) 按国家聚合把省份细分的行累加为整国数据 infected infected.groupby(Country/Region).sum() recovered recovered.groupby(Country/Region).sum() deaths deaths.groupby(Country/Region).sum() # 2) 去掉非日期的元数据列 infected.drop(columns[Lat, Long, Province/State], inplaceTrue) recovered.drop(columns[Lat, Long, Province/State], inplaceTrue) deaths.drop(columns[Lat, Long, Province/State], inplaceTrue) # 3) 封装“按国家构建时间序列帧”的函数日期列转 datetime def mkframe(country): df pd.DataFrame({infected: infected.loc[country], recovered: recovered.loc[country], deaths: deaths.loc[country]}) df.index pd.to_datetime(df.index) return df df mkframe(US)关键点在于groupby(Country/Region).sum()让 DataFrame 以国家为索引之后用.loc[country]即可取到单国数据diff()用于把累计感染数转换为每日新增感染数rolling(window7).mean()则用于抹平数据中的周度波动报告周期导致的锯齿df[ninfected] df[infected].diff() # 每日新增 df[ninfav] df[ninfected].rolling(7).mean() # 7 日均线消除周度波动如果要在不同国家之间比较疫情规模Notebook 还给出了人口归一化的做法——从 UID_ISO_FIPS_LookUp_Table.csv 中按“国家 无省份细分”取出人口数换算成感染占比pop countries[(countries[Country_Region] US) countries[Province_State].isna()][Population].iloc[0] df[pinfected] df[infected] * 100 / pop第一部分COVID-19 疫情传播建模这一部分的 R_t 计算是 Notebook 的核心铺垫。Notebook 用 8 天滚动窗口估计随时间变化的再生数 R_tdf[Rt] df[ninfected].rolling(8).apply(lambda x: x[4:].sum() / x[:4].sum()) df[Rt].plot()实现细节说明8 天窗口内的 8 个值为从旧到新的每日新增感染数x[:4]是窗口前 4 天之和x[4:]是后 4 天之和。值得注意Notebook 中公式文本写作 R_t(I_{t-7}…I_{t-4})/(I_{t-3}…I_t)与代码方向互为倒数两种写法语义上都刻画“当前新增相对前几天”的放大倍数实际计算以代码为准。当 R_t1 时说明疫情仍在扩张R_t1 则意味着传播在收敛。由于 R_t 是比率天然不受国家人口规模影响可以直接跨国家比较。绘制前建议先清理inf/NaN——窗口不足 8 天时结果为 NaN除零会产生inf。Notebook 的标准清理手法是ax df[df.index 2020-05-01][Rt].replace(np.inf, np.nan).fillna(methodpad).plot(figsize(10, 3)) ax.set_ylim([0, 6]) # 只看 0~6 区间便于观察 ax.axhline(1, linestyle--, colorred) # 参考线 R_t1 plt.show()兼容性提示较新版本 Pandas 已弃用fillna(methodpad)可等价替换为.fillna(methodffill)或直接.ffill()。任务 1为 5~6 个国家绘制 R_t 对比图把上面的 R_t 计算封装成函数然后对多国循环取值、绘制在同一坐标系内即可完成对比def compute_rt(country): d mkframe(country) d[ninfected] d[infected].diff() rt d[ninfected].rolling(8).apply(lambda x: x[4:].sum() / x[:4].sum()) return rt.replace(np.inf, np.nan).ffill() countries_list [US, Brazil, India, Russia, UK, Germany] plt.figure(figsize(12, 6)) for c in countries_list: compute_rt(c).plot(labelc) plt.ylim(0, 6) plt.axhline(1, linestyle--, colorred) plt.legend() plt.show()也可以用plt.subplots(2, 3)并排画出多个子图逐个观察各国 R_t 的峰谷形态。R_t 高于 1 的时段越长说明该国疫情扩张持续越久。任务 2死亡数、康复数与感染数的相关性Notebook 已经构造了同时包含infected、recovered、deaths三列的时间序列帧直接计算相关系数矩阵即可df mkframe(US) print(df[[infected, recovered, deaths]].corr())更直观的做法是用散点图看两两关系df.plot.scatter(xinfected, ydeaths)。由于康复与死亡都滞后于感染先验上它们与感染数应呈强正相关如果你发现相关性偏弱多半是时间滞后导致的可以顺带对比不同滞后天数下的相关系数——这正好为任务 3 和任务 4 埋下伏笔。任务 3推断典型病程任务 3 的思路是“用平移对齐两条时间序列”死亡/康复曲线整体滞后于感染曲线滞后天数约等于从感染到结局的平均病程。Notebook 的作业提示也明确建议“按病程天数平移一条时间序列后再计算”。可行的做法是扫描不同的平移天数 d计算“感染曲线”与“前移 d 天的死亡曲线”的相关系数取相关系数最大的 d 作为病程估计def best_lag(df, coldeaths, max_lag40): res [] for d in range(0, max_lag): corr df[col].shift(-d).corr(df[infected]) res.append((d, corr)) return max(res, keylambda t: t[1]) print(best_lag(mkframe(US)))这里的逻辑是今天的死亡数对应约 d 天前的感染数因此把死亡序列向前shift(-d)移动 d 天后两条曲线应最大程度重合。不同国家的报告节奏、医疗条件不同最佳滞后天数会有差异任务要求你“多对比几个国家并寻找异常点”——比如数据上报集中导致的陡峰、或者疫情暴发早期的高致死率时段都会在曲线对位上留下痕迹。任务 4致死率及其随时间的变化致死率最基本的定义是死亡数除以确诊数df[fatality] df[deaths] / df[infected] df[fatality].plot()但正如作业提示所说这个指标存在时间错位问题分母用的是“今天”的累计确诊而分子对应的是“若干天前”确诊的那批病人的结局因此早期病例尚未结束病程时致死率会被系统性低估。更严谨的做法是先按任务 3 得到的滞后天数平移lag best_lag(mkframe(US))[0] df[fatality_lagged] df[deaths] / df[infected].shift(lag) df[fatality_lagged].plot()把两种定义画在同一张图上对比通常能看到平移后的致死率更平稳且能更早反映真实水平的变化趋势。这正是作业想要你体会的“数据对齐”思想。第二部分COVID-19 论文分析这一部分处理的是非结构化文本数据核心方法论是“先从摘要中抽取结构化计数再做矩阵运算与可视化”。Notebook 的做法是手动维护两份实体清单然后用“带前导空格的子串匹配”统计每个词在摘要中出现的次数medications [hydroxychloroquine, chloroquine, tocilizumab, remdesivir, azithromycin, lopinavir, ritonavir, dexamethasone, heparin, favipiravir, methylprednisolone] for m in medications: df[m] df[abstract].apply(lambda x: str(x).lower().count( m))易错点Notebook 专门提示匹配时一定要在词首加空格 m否则chloroquine会被包含它的hydroxychloroquine错误命中同时用str(x)强制转字符串以避免缺失值报错。有了逐篇摘要的计数列就能按时间聚合观察治疗策略的演变月度groupby 求和Notebook 还演示了用plot.area()堆叠面积图和归一化百分比图来展示不同药物的相对热度变化。下图是论文分析部分的典型输出——不同药物随发表时间变化的堆叠面积图任务 1构建药物共现矩阵共现矩阵的本质是一个二维计数数组对每一篇摘要凡是同时出现两种药物就在对应格子上加 1。Notebook 里“药物×诊断”矩阵的构建代码是m np.zeros((len(medications), len(diagnosis))) for a in df[abstract]: x str(a).lower() for i, d in enumerate(diagnosis): if d in x: for j, me in enumerate(medications): if me in x: m[j, i] 1作业要求你照此模式改造为“药物×药物”矩阵从而回答“哪些药物经常被一起研究”n len(medications) m np.zeros((n, n)) for a in df[abstract]: x str(a).lower() present [i for i, med in enumerate(medications) if med in x] for i in present: for j in present: m[i, j] 1注意对角线上的值表示该药物被提及的总篇数同一药物与自己共现分析共现强度时通常只看非对角元素如需消除规模差异可进一步把计数归一化为 Jaccard 相似度或除以对角线得到条件概率。任务 2用 heatmap 可视化共现矩阵Notebook 对“药物×诊断”矩阵的 heatmap 画法可直接复用只需把行标签与列标签都换成药物名plt.figure(figsize(10, 8)) plt.imshow(m, interpolationnearest, cmaphot) ax plt.gca() ax.set_yticks(range(len(medications))) ax.set_yticklabels(medications) ax.set_xticks(range(len(medications))) ax.set_xticklabels(medications, rotation90) plt.colorbar() plt.show()矩阵中颜色越亮的格子对应的药物对共现越频繁。结合任务 1 的计数你应当能识别出类似“羟氯喹 阿奇霉素”“洛匹那韦 利托那韦”这类常被组合研究的方案。拓展目标一用 chord diagram 可视化药物共现作业给出的拓展思路是使用chord库绘制弦图把共现矩阵变成更美观的关系图# pip install chord from chord import Chord # 构造 chord 库需要的矩阵与标签API 细节以该库文档为准 Chord(m, medications).show()弦图把每种药物作为圆周上的一个节点节点之间的弦越粗表示共现越强适合一眼看清“谁和谁绑定出现”。如果矩阵不对称通常需要先对称化如取m m.T再传给弦图库。拓展目标二用正则表达式抽取药物剂量最后一项拓展目标是把“剂量”从自然语言中抽出来例如从take 400mg of chloroquine daily中抽到400mg。作业提示的关键约束是只取药物名附近文本距离内的数值避免抽到与用药无关的数字。实现思路是“先定位药物名再在它前后开一个窗口在窗口内用正则匹配剂量单位”import re dosage_pattern re.compile(r(\d(?:\.\d)?)\s*(mg|mcg|µg|g|iu|ml)\b, re.IGNORECASE) def extract_dosages(abstract, meds, window50): rows [] x str(abstract).lower() for med in meds: for match in re.finditer(r\b re.escape(med) r\b, x): start max(0, match.start() - window) end min(len(x), match.end() window) context x[start:end] for dose, unit in dosage_pattern.findall(context): rows.append((med, f{dose}{unit.lower()})) return rows records [] for a in df[abstract]: records.extend(extract_dosages(a, medications)) dosage_df pd.DataFrame(records, columns[medication, dosage]) dosage_df.value_counts().head(20)window参数控制“药物名前后多少字符内才算关联数值”\b词边界避免400mg内部或词缀造成的误匹配。最终dosage_df就是一个“药物 × 剂量”的 DataFrame可以通过value_counts统计最常见剂量或按药物分组查看剂量分布。评分标准Rubric作业原文附带了明确的评分表可以作为自检清单等级要求Excellent优秀所有任务全部完成有图形化展示与文字解释且至少完成两个拓展目标中的一个Adequate合格完成任务超过 5 项未尝试拓展目标或结果不够清晰Needs Improvement待改进完成任务少于 5 项但多于 3 项且可视化未能有效支撑结论按此标准规划工作量第一部分 4 项 第二部分 2 项为必做底线想拿“优秀”必须再攻坚任一拓展目标弦图或剂量抽取。评分同时强调“可视化必须能证明观点”——不是画了图就算完成图中必须能读出任务要求回答的问题。总结与延伸这份作业完整覆盖了数据科学实战的典型链路宽表整形 → 时间序列特征工程差分、滚动窗口、平移对齐→ 统计度量相关性、比率→ 文本结构化抽取 → 矩阵构建 → 可视化验证。你既可以用 notebook-covidspread.ipynb 的疫情数据练手 Pandas 时间序列操作也可以在 notebook-papers.ipynb 的论文文本上体会“非结构化数据如何变成结构化洞察”。Pandas 基础概念Series、DataFrame、groupby、apply、resample可回看 notebook.ipynb 与课程 README 巩固。完成作业后还可以继续沿着 Notebook 的参考文献方向探索例如把“手动词表”换成真正的 NLP 实体抽取如 NLTK 或云端文本分析服务或对 R_t 估计引入更精细的滑动 SIR 模型——这些进阶方向都能让同一份数据产生更深的结论。【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表