news 2026/9/23 0:02:06

3个Python脚本搞定抑郁症数据速查手册搭建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
3个Python脚本搞定抑郁症数据速查手册搭建

3个Python脚本搞定抑郁症数据速查手册搭建

刚学完Python语法,对着空白的编辑器发呆?别急,这是90%新手都会遇到的“代码孤岛”困境。你会写 for 循环,会定义函数,但一让你搭个完整项目,脑子就一片空白。今天不聊虚的,直接上干货。我们要用Python从零搭建一个针对抑郁症筛查数据的自动化速查手册生成器。这不是为了做医疗诊断,而是为了帮助心理工作者、社区医生或HR快速整理患者自评量表(如PHQ-9)的统计分布、风险等级分类和关键指标汇总。很多机构还在用Excel手动统计,效率低且容易出错。我们要把这个过程代码化、自动化,生成一份清晰、可检索的PDF或Markdown格式速查手册

项目目标与数据清洗

先明确我们要解决什么痛点。心理评估量表的数据通常是CSV或Excel格式,里面混杂着缺失值、异常值和不同编码格式的评分。我们的目标是:输入原始数据,输出结构化的风险分布报表。

这里有个关键细节:数据标准化。不同机构对“轻度抑郁”的分数段定义可能略有差异。我们参考GitHub开源仓库 psychometrics-tools 中的PHQ-9标准切分点,确保算法符合主流临床标准。

第一步是环境准备。你需要Python 3.8+,以及 pandasnumpy 这两个核心库。安装很简单:

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\n"md_content += f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"md_content += f"## 总体概览\n\n"md_content += f"- **样本总量**: {stats['total_count']} 人\n"md_content += f"- **平均分**: {stats['avg_score']}\n"md_content += f"- **中位数**: {stats['median_score']}\n\n"md_content += f"## 风险等级分布\n\n"md_content += f"| 风险等级 | 人数 | 占比 (%) |\n"md_content += f"| :--- | :---: | :---: |\n"# 遍历风险等级,生成表格行for level, data in stats['risk_distribution'].items():md_content += f"| {level} | {data['count']} | {data['percent']} |\n"md_content += f"\n## 建议与注意事项\n\n"md_content += f"1. 数据仅供统计参考,不能作为临床诊断依据。\n"md_content += f"2. '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 = f"depression_report_{get_current_date_string()}.md"output_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. 性能优化 如果数据量极大,pandasapply 函数会变慢。可以尝试向量化操作,或者使用 numpy 的直接索引。对于实时性要求高的场景,可以考虑引入 polars 库,它的速度比 pandas 快一个数量级。

2. 可视化增强 纯文本表格虽然清晰,但不够直观。引入 matplotlibplotly,生成柱状图或饼图,并嵌入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 列进行哈希处理,确保速查手册中不包含任何可识别个人身份的信息。这是合规的底线。

小结

从学会语法到搭建项目,中间隔着的是工程化思维。今天这个抑郁症数据速查手册项目,虽然功能简单,但涵盖了数据清洗、模块化设计、自动化报表生成等核心技能。你不再是一个只会写片段的人,而是一个能交付完整解决方案的工程师。

这个项目可以直接作为你简历上的一个案例。它展示了你处理真实业务数据的能力,以及对细节(如数据清洗、边界处理)的关注。更重要的是,它解决了“学会语法却不知怎么搭项目”的焦虑。你有了模板,有了思路,接下来就是替换数据源,适应你的具体业务场景。

编程不是背代码,而是解决问题。当你能够用代码自动化地整理一份抑郁症筛查报告时,你就已经跨过了新手村。

你公司项目里是怎么处理的?欢迎评论

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 0:01:33

3个实战技巧搞定形式英语:从看教程到跑通性能优化

3个实战技巧搞定形式英语:从看教程到跑通性能优化 看了一堆教程还是不会写项目?别慌,这种“眼高手低”的困境在开发者圈子里太常见了。很多人以为卡点在语法,其实真正拦路虎是缺乏将知识点串联成完整链路的能力。今天咱们不聊虚的,直接拿【形式英语】这个高频场景开刀,看看如何把它从一堆死记硬背的字符串,变成可复…

作者头像 李华
网站建设 2026/9/23 0:01:33

norse ipviking 避坑指南:3 个致命错误拖垮项目性能优化

norse ipviking 避坑指南:3 个致命错误拖垮项目性能优化 看了一堆教程还是不会写项目?别急,问题往往不在语法,而在底层逻辑的误解。很多开发者在使用 norse ipviking 相关技术栈时,陷入了“能跑就行”的陷阱,直到生产环境出现延迟飙升才惊觉, 性能优化…

作者头像 李华
网站建设 2026/9/23 0:01:18

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API 全变了,连个警告都没有,直接白屏。做前端和后端都懂这种痛,尤其是涉及底层图形渲染或高分辨率适配时,性能优化…

作者头像 李华
网站建设 2026/9/23 0:01:09

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。 项目目标与需求拆解 美眉图(Meme…

作者头像 李华
网站建设 2026/9/23 0:01:05

3步搞定黄金大劫案项目搭建从入门到精通

3步搞定黄金大劫案项目搭建从入门到精通 学会语法却不知怎么搭项目,是无数开发者的死穴。别盯着教程里的Hello World看,真上手一做就懵,这才是阻碍你从入门到精通的真实拦路虎。今天咱们不整虚的,直接拆解一个名为【黄金大劫案】的实战项目。…

作者头像 李华
网站建设 2026/9/23 0:01:04

张文成面试突击:3招搞定性能优化报错

张文成面试突击:3招搞定性能优化报错 看着满屏红色的 StackTrace,心里是不是咯噔一下? 别慌,这堆报错看着吓人,其实 80% 都是性能优化的坑。 今天拆解张文成相关的高频考点,带你把报错变分数。 考点梳理:别被名字骗了 很多新手听到“张文成”,第一反应是“这谁?”。…

作者头像 李华