3个Python脚本搞定抑郁症数据速查手册搭建
刚学完Python语法,对着空白的编辑器发呆?别急,这是90%新手都会遇到的“代码孤岛”困境。你会写 for 循环,会定义函数,但一让你搭个完整项目,脑子就一片空白。今天不聊虚的,直接上干货。我们要用Python从零搭建一个针对抑郁症筛查数据的自动化速查手册生成器。这不是为了做医疗诊断,而是为了帮助心理工作者、社区医生或HR快速整理患者自评量表(如PHQ-9)的统计分布、风险等级分类和关键指标汇总。很多机构还在用Excel手动统计,效率低且容易出错。我们要把这个过程代码化、自动化,生成一份清晰、可检索的PDF或Markdown格式速查手册。
项目目标与数据清洗
先明确我们要解决什么痛点。心理评估量表的数据通常是CSV或Excel格式,里面混杂着缺失值、异常值和不同编码格式的评分。我们的目标是:输入原始数据,输出结构化的风险分布报表。
这里有个关键细节:数据标准化。不同机构对“轻度抑郁”的分数段定义可能略有差异。我们参考GitHub开源仓库 psychometrics-tools 中的PHQ-9标准切分点,确保算法符合主流临床标准。
第一步是环境准备。你需要Python 3.8+,以及 pandas 和 numpy 这两个核心库。安装很简单:
pip install pandas numpy接下来是数据加载与清洗。假设我们有一个 phq9_raw.csv 文件,包含 id, score, date, notes 四列。
import pandas as pd
import numpy as npdef load_and_clean_data(file_path):# 1. 读取CSV文件df = pd.read_csv(file_path)# 2. 处理缺失值:如果score为空,标记为'unknown',后续单独统计df['score'] = df['score'].fillna(-1)# 3. 过滤无效数据:PHQ-9总分范围是0-27,超出视为异常df = df[(df['score'] = 0) (df['score'] = 27)]# 4. 根据标准切分风险等级# 0-4: 无/极轻微, 5-9: 轻度, 10-14: 中度, 15-19: 中重度, 20-27: 重度def categorize_risk(score):if score = 4:return 'Low'elif score = 9:return 'Mild'elif score = 14:return 'Moderate'elif score = 19:return 'Moderately Severe'else:return 'Severe'df['risk_level'] = df['score'].apply(categorize_risk)return df这段代码的逻辑非常清晰。fillna(-1) 是个小技巧,先占位再过滤,避免直接删除行导致数据量骤降。categorize_risk 函数是核心,它把连续的分数离散化为五个等级,这是生成速查手册中“风险分布图表”的基础。
目录结构设计
一个可维护的项目,目录结构比代码本身更重要。很多新手喜欢把所有代码塞进一个 main.py,这是大忌。我们采用模块化设计:
depression_manual_gen/
├── data/
│ └── phq9_raw.csv # 原始数据
├── src/
│ ├── __init__.py
│ ├── data_processor.py # 数据清洗与分类逻辑
│ ├── report_generator.py # 报表生成逻辑
│ └── utils.py # 通用工具函数
├── output/
│ └── generated/ # 最终生成的手册文件
├── requirements.txt # 依赖库列表
└── main.py # 程序入口在 src/utils.py 中,我们写一些通用函数,比如日期格式化、文件路径处理:
import os
from datetime import datetimedef ensure_dir_exists(path):确保目录存在,不存在则创建if not os.path.exists(path):os.makedirs(path)return pathdef get_current_date_string():获取当前日期字符串,用于文件命名return datetime.now().strftime(%Y%m%d)这种结构的好处是,当你要更换数据源(比如从CSV换成SQL数据库)时,只需要修改 data_processor.py,而不用动报表生成逻辑。这就是工程化的意义。
核心代码实现
现在进入最核心的部分:统计分析与报表生成。我们要计算每个风险等级的占比、平均分、以及环比变化(如果有历史数据)。
在 src/report_generator.py 中,我们实现统计逻辑:
import pandas as pddef generate_statistics(df):生成统计摘要:param df: 清洗后的DataFrame:return: dict 包含各项统计指标# 1. 计算总人数total_count = len(df)# 2. 计算各风险等级人数risk_counts = df['risk_level'].value_counts()# 3. 计算各等级占比risk_percentages = (risk_counts / total_count) * 100# 4. 计算总体平均分avg_score = df['score'].mean()# 5. 计算中位数,排除极端值影响median_score = df['score'].median()# 构建结果字典stats = {'total_count': total_count,'avg_score': round(avg_score, 2),'median_score': round(median_score, 2),'risk_distribution': {'Low': {'count': int(risk_counts.get('Low', 0)), 'percent': round(risk_percentages.get('Low', 0), 2)},'Mild': {'count': int(risk_counts.get('Mild', 0)), 'percent': round(risk_percentages.get('Mild', 0), 2)},'Moderate': {'count': int(risk_counts.get('Moderate', 0)), 'percent': round(risk_percentages.get('Moderate', 0), 2)},'Moderately Severe': {'count': int(risk_counts.get('Moderately Severe', 0)), 'percent': round(risk_percentages.get('Moderately Severe', 0), 2)},'Severe': {'count': int(risk_counts.get('Severe', 0)), 'percent': round(risk_percentages.get('Severe', 0), 2)}}}return stats注意这里的 round 函数,保留两位小数是报表的惯例,既精确又整洁。risk_distribution 是一个嵌套字典,方便后续直接渲染成Markdown表格。
接下来,我们把统计结果转换成Markdown格式的速查手册。Markdown比PDF更灵活,可以直接在GitHub或Confluence中查看。
def generate_markdown_report(stats, output_path):生成Markdown格式报表:param stats: 统计字典:param output_path: 输出文件路径# 构建Markdown内容md_content = f# 抑郁症筛查数据速查手册\n\nmd_content += f**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\nmd_content += f## 总体概览\n\nmd_content += f- **样本总量**: {stats['total_count']} 人\nmd_content += f- **平均分**: {stats['avg_score']}\nmd_content += f- **中位数**: {stats['median_score']}\n\nmd_content += f## 风险等级分布\n\nmd_content += f| 风险等级 | 人数 | 占比 (%) |\nmd_content += f| :--- | :---: | :---: |\n# 遍历风险等级,生成表格行for level, data in stats['risk_distribution'].items():md_content += f| {level} | {data['count']} | {data['percent']} |\nmd_content += f\n## 建议与注意事项\n\nmd_content += f1. 数据仅供统计参考,不能作为临床诊断依据。\nmd_content += f2. 'Severe'等级人群建议优先进行专业评估。\n# 写入文件with open(output_path, 'w', encoding='utf-8') as f:f.write(md_content)print(f报表已生成: {output_path})这段代码的关键在于 f-string 的灵活运用。它让动态内容插入变得非常直观。特别是表格生成部分,通过循环拼接字符串,实现了从数据到可视化的直接转换。
运行与测试
万事俱备,只欠东风。在 main.py 中串联所有模块:
import os
from src.data_processor import load_and_clean_data
from src.report_generator import generate_statistics, generate_markdown_report
from src.utils import ensure_dir_exists, get_current_date_stringdef main():# 1. 配置路径data_file = 'data/phq9_raw.csv'output_dir = 'output/generated'ensure_dir_exists(output_dir)# 2. 生成带日期的文件名filename = fdepression_report_{get_current_date_string()}.mdoutput_file = os.path.join(output_dir, filename)# 3. 执行流程try:# 加载与清洗print(正在加载与清洗数据...)df = load_and_clean_data(data_file)# 统计print(正在计算统计数据...)stats = generate_statistics(df)# 生成报表print(正在生成Markdown报表...)generate_markdown_report(stats, output_file)print(任务完成!)except FileNotFoundError:print(f错误: 找不到数据文件 {data_file})except Exception as e:print(f发生未知错误: {e})if __name__ == __main__:main()运行 python main.py,你应该会在控制台看到进度提示,并在 output/generated 目录下得到一个 .md 文件。用VS Code打开它,你会看到一个排版整洁的表格,清晰展示了各风险等级的人数和占比。
测试环节不能少。你可以手动修改几行数据,比如把某个 score 改成28(超出范围),运行后确认它被正确过滤。或者把 score 设为空值,确认它被标记并排除在平均分计算之外。这种边界测试是保证生产环境稳定性的关键。
优化扩展
基础版本跑通了,但这只是起点。实际工作中,数据量可能达到十万级,或者需要更复杂的分析。这里有几个优化方向:
1. 性能优化
如果数据量极大,pandas 的 apply 函数会变慢。可以尝试向量化操作,或者使用 numpy 的直接索引。对于实时性要求高的场景,可以考虑引入 polars 库,它的速度比 pandas 快一个数量级。
2. 可视化增强
纯文本表格虽然清晰,但不够直观。引入 matplotlib 或 plotly,生成柱状图或饼图,并嵌入Markdown中。例如:
import matplotlib.pyplot as pltdef plot_risk_distribution(stats):levels = list(stats['risk_distribution'].keys())counts = [stats['risk_distribution'][level]['count'] for level in levels]plt.figure(figsize=(10, 6))plt.bar(levels, counts, color=['#2ecc71', '#f1c40f', '#e67e22', '#e74c3c', '#c0392b'])plt.title('Depression Risk Distribution')plt.ylabel('Count')plt.tight_layout()plt.savefig('output/generated/risk_chart.png', dpi=150)3. 自动化部署
利用 cron (Linux) 或任务计划程序 (Windows),每天凌晨自动运行脚本,将最新报表推送到企业微信或钉钉群。结合 Git,可以将生成的报表提交到内部仓库,形成历史趋势对比。
4. 隐私保护
医疗数据敏感。在 data_processor.py 中增加脱敏逻辑,比如对 id 列进行哈希处理,确保速查手册中不包含任何可识别个人身份的信息。这是合规的底线。
小结
从学会语法到搭建项目,中间隔着的是工程化思维。今天这个抑郁症数据速查手册项目,虽然功能简单,但涵盖了数据清洗、模块化设计、自动化报表生成等核心技能。你不再是一个只会写片段的人,而是一个能交付完整解决方案的工程师。
这个项目可以直接作为你简历上的一个案例。它展示了你处理真实业务数据的能力,以及对细节(如数据清洗、边界处理)的关注。更重要的是,它解决了“学会语法却不知怎么搭项目”的焦虑。你有了模板,有了思路,接下来就是替换数据源,适应你的具体业务场景。
编程不是背代码,而是解决问题。当你能够用代码自动化地整理一份抑郁症筛查报告时,你就已经跨过了新手村。
你公司项目里是怎么处理的?欢迎评论
企业数字化 ERP 产品动态
相关推荐
3个实战技巧搞定形式英语:从看教程到跑通性能优化 3个实战技巧搞定形式英语:从看教程到跑通性能优化 看了一堆教程还是不会写项目?别慌,这种“眼高手低”的困境在开发者圈子里太常见了。很多人以为卡点在语法,其实真正拦路虎是缺乏将知识点串联成完整链路的能力。今天咱们不聊虚的,直接拿【形式英语】这… · 2026/9/23 0:01:39
3个坑讲透typically性能优化一文搞懂面试原理 3个坑讲透typically性能优化一文搞懂面试原理 面试被问原理答不上来,是后端开发最尴尬的时刻。 尤其是提到 typically 这种看似简单实则深奥的性能场景。 今天带你一文搞懂,如何把这类高频考点变成你的加分项。… · 2026/9/23 1:28:37
【Agent实战】Agent Skills 深度解析:从 SKILL.md 到 MCP 的落地配置指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/23 1:28:37
Spring Boot+Vue+MyBatisPlus 学生成绩管理系统实战解析 简介:一份面向Java开发者的前后端分离项目实战教程,以学生成绩管理系统为例,完整演示Spring Boot、Vue.js与MyBatisPlus三者的整合开发。资源只有一个PDF文件,整体大小为2.8MB,内容从数据库设计讲起,逐步推… · 2026/9/23 1:28:31
基于深度学习的Shack-Hartmann波前重建:Matlab仿真实现与关键技巧 简介:基于深度学习和Shack-Hartmann波前传感器的波前重建Matlab仿真项目,面向光学、计算机、电子信息及数学等专业学生和科研人员,适用于课程设计、期末大作业和毕业设计。资源共包含46个文件,压缩包1.84MB,核心包括20… · 2026/9/23 1:28:25
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29