ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Python数据科学实战:上市公司财务风险预测全流程解析

2026/9/2 10:36:39 拓冰建站 浏览量
Python数据科学实战:上市公司财务风险预测全流程解析 大家好我是CSDN的一名技术博主。最近在辅导一些非计算机专业如会计、金融的同学完成他们的“数据科学与人工智能导论”课程实践时发现一个普遍痛点大家虽然对概念有所了解但面对一个具体的、需要从数据到模型再到分析报告的完整项目时往往无从下手代码、流程、报告撰写都是割裂的。本文将以一份面向会计专业的期末实践报告为蓝本系统拆解如何完成一个数据科学项目。我们将从一个真实的财务数据集出发完整走过数据获取、清洗、探索性分析、机器学习建模、结果可视化与商业解读的全流程并提供所有可复现的Python代码。无论你是零基础的会计专业学生还是想了解如何将AI应用于业务分析的开发者都能从这篇实战指南中获得一套可直接套用的方法论。1. 项目背景与核心目标本次实践报告的核心是利用数据科学与人工智能技术对上市公司财务数据进行分析与预测并给出商业洞察。对于会计专业的同学而言这不仅是完成课程作业更是将所学的会计原理、财务分析与前沿的数据工具相结合的一次宝贵实践。1.1 为什么会计专业需要学习数据科学在现代商业环境中财务数据已不再是简单的报表数字。海量的交易数据、市场数据和运营数据中蕴藏着关于企业健康度、风险预警和未来趋势的关键信息。传统手工分析难以处理这种规模与复杂度的数据。数据科学提供了强大的工具如Python, Pandas, Scikit-learn来自动化数据处理、发现深层模式、甚至构建预测模型如破产预测、股价趋势分析从而提升财务分析的效率、深度与前瞻性。1.2 项目核心目标拆解我们的项目将围绕以下几个可量化、可验证的目标展开目标一数据理解与清洗。获取一份真实的上市公司财务数据集理解每个字段的财务含义并处理缺失值、异常值使数据可用于分析。目标二探索性数据分析。通过统计描述与可视化初步揭示数据特征如不同行业公司的盈利能力分布、资产与负债的关系等。目标三构建预测模型。选择一个具体的预测任务例如根据一系列财务指标如资产负债率、净资产收益率来预测公司是否会被特殊处理ST。我们将使用经典的机器学习算法来完成此任务。目标四模型评估与解释。评估模型的预测性能并尝试解释哪些财务指标对预测结果影响最大将机器学习结果转化为可理解的商业语言。目标五形成综合报告。将以上所有步骤、代码、结果和分析逻辑整合成一份结构清晰、图文并茂的实践报告。2. 环境准备与工具说明工欲善其事必先利其器。我们选择Python作为主要工具因为它拥有极其丰富且易用的数据科学库生态系统。2.1 基础环境配置操作系统Windows 10/11, macOS 或 Linux 均可。本文示例在Windows 11下完成。Python版本推荐使用 Python 3.8 至 3.10。版本过高可能导致某些库兼容性问题。包管理工具使用pip或更推荐的conda如果你安装了Anaconda。2.2 核心Python库安装我们将使用以下库请通过命令行CMD或终端安装# 使用 pip 安装 pip install pandas numpy matplotlib seaborn scikit-learn jupyter # 或者使用 conda 安装 conda install pandas numpy matplotlib seaborn scikit-learn jupyterpandas数据操作的基石用于数据读取、清洗、转换和分析。numpy提供高性能的数组计算是许多科学计算库的基础。matplotlibseaborn数据可视化库用于绘制各种统计图表。scikit-learn机器学习库提供了分类、回归、聚类等大量算法和评估工具。jupyter交互式笔记本环境非常适合分步执行代码和展示结果是撰写数据分析报告的绝佳工具。2.3 项目结构与数据集项目结构建议创建一个清晰的文件夹。your_project/ ├── data/ │ └── listed_companies_financial.csv # 数据集 ├── images/ # 存放生成的图表 ├── 财务数据分析与预测.ipynb # Jupyter Notebook主文件 └── 期末实践报告.pdf # 最终生成的报告数据集我们将使用一个模拟的上市公司财务数据集。为了便于复现你可以从Kaggle、UCI或国内一些公开数据平台寻找类似数据集如“上市公司财务指标”。本文为了演示将使用代码生成一个包含关键财务指标的模拟数据集。3. 核心概念与流程拆解在动手编码前我们需要理解一个标准的数据科学项目流程即CRISP-DM(跨行业数据挖掘标准流程) 的简化版。3.1 业务理解对应我们的项目目标利用财务数据预测公司风险ST状态为投资或风控提供参考。3.2 数据理解与准备这是最耗时但也最关键的一步。涉及数据收集获取包含股票代码、行业、净利润、资产负债率、流动比率、净资产收益率(ROE)、总资产周转率等字段的数据。数据清洗处理缺失值删除或填充如用中位数填充。处理异常值识别并处理远超正常范围的数值。格式统一确保数字字段为数值型日期字段为日期型。特征工程从原始字段中衍生出更有预测力的新特征。例如计算“净利润增长率”。3.3 建模选择合适的算法。对于“预测是否ST”这样的二分类问题我们可以选择逻辑回归模型简单可解释性强适合作为基线模型。决策树/随机森林能捕捉非线性关系通常有不错的性能。支持向量机在高维空间表现良好。 我们将以逻辑回归和随机森林为例进行对比。3.4 评估使用未参与模型训练的数据测试集来评估模型性能。常用指标包括准确率预测正确的样本比例。精确率、召回率、F1-score尤其适用于类别不平衡的数据ST公司通常远少于非ST公司。ROC曲线与AUC值综合评价模型分类能力的指标。3.5 部署与报告将分析过程、代码、结果可视化并提炼核心发现形成最终报告。4. 完整实战上市公司财务风险预测接下来我们将在Jupyter Notebook中一步步实现整个流程。4.1 数据加载与初步探索首先我们生成一个模拟数据集并进行初步查看。# 导入必要的库 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, roc_auc_score, roc_curve # 设置中文显示和图表样式 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负号 sns.set_style(whitegrid) # 生成模拟数据 np.random.seed(42) # 确保每次运行结果一致 n_samples 1000 data { stock_code: [fSTK{str(i).zfill(6)} for i in range(n_samples)], industry: np.random.choice([制造业, 信息技术, 金融业, 零售业, 房地产业], n_samples), net_profit: np.random.normal(50, 200, n_samples), # 净利润百万 asset_liability_ratio: np.random.uniform(0.1, 0.9, n_samples), # 资产负债率 current_ratio: np.random.uniform(0.5, 3.0, n_samples), # 流动比率 roe: np.random.normal(0.08, 0.15, n_samples), # 净资产收益率 total_asset_turnover: np.random.uniform(0.2, 1.5, n_samples), # 总资产周转率 } df pd.DataFrame(data) # 模拟生成目标变量 is_st (1表示ST0表示非ST) # 规则资产负债率过高、ROE为负、净利润为负的公司更可能被ST def simulate_st(row): risk_score 0 if row[asset_liability_ratio] 0.7: risk_score 2 if row[roe] 0: risk_score 2 if row[net_profit] -10: # 净亏损较大 risk_score 1 # 引入随机性 return 1 if (risk_score 3 and np.random.rand() 0.3) else 0 df[is_st] df.apply(simulate_st, axis1) print(数据集形状行数列数:, df.shape) print(\n数据前5行) print(df.head()) print(\n数据基本信息) print(df.info()) print(\n数值型字段描述性统计) print(df.describe()) print(\n目标变量分布ST vs 非ST) print(df[is_st].value_counts()) print(ST公司占比{:.2%}.format(df[is_st].mean()))运行以上代码你会看到数据的基本情况1000条记录8个字段其中is_st是我们的目标变量。可以看到ST公司占比大约在10%左右这是一个典型的类别不平衡数据集。4.2 数据清洗与预处理现实数据往往不完美我们需要进行处理。# 1. 检查缺失值 print(缺失值统计) print(df.isnull().sum()) # 本例中模拟数据无缺失若有缺失常用处理方式 # df.fillna(df.median(), inplaceTrue) # 用中位数填充数值列 # df.dropna(inplaceTrue) # 或直接删除缺失行 # 2. 检查并处理异常值以净资产收益率ROE为例 plt.figure(figsize(10, 4)) plt.subplot(1,2,1) sns.boxplot(ydf[roe]) plt.title(ROE箱线图处理前) # 使用IQR方法识别异常值 Q1 df[roe].quantile(0.25) Q3 df[roe].quantile(0.75) IQR Q3 - Q1 lower_bound Q1 - 1.5 * IQR upper_bound Q3 1.5 * IQR outliers df[(df[roe] lower_bound) | (df[roe] upper_bound)] print(f\nROE异常值数量{len(outliers)}) # 处理异常值这里采用盖帽法将极端值拉回到边界 df[roe_capped] df[roe].clip(lower_bound, upper_bound) plt.subplot(1,2,2) sns.boxplot(ydf[roe_capped]) plt.title(ROE箱线图盖帽法处理后) plt.tight_layout() plt.show() # 3. 特征工程创建衍生特征 df[profit_margin] df[net_profit].apply(lambda x: 1 if x 0 else 0) # 是否盈利 # 可以创建更多特征如行业平均ROE等此处简化 # 4. 对分类特征行业进行编码 df pd.get_dummies(df, columns[industry], prefixind) print(\n进行独热编码后的数据列) print(df.columns.tolist())4.3 探索性数据分析通过可视化深入理解数据。# 1. 目标变量分布 plt.figure(figsize(12, 10)) plt.subplot(2, 2, 1) df[is_st].value_counts().plot(kindbar, color[skyblue, salmon]) plt.title(ST与非ST公司数量对比) plt.xlabel(是否ST (1是)) plt.ylabel(公司数量) for i, v in enumerate(df[is_st].value_counts().sort_index()): plt.text(i, v10, str(v), hacenter) # 2. 关键财务指标分布 plt.subplot(2, 2, 2) sns.histplot(df[asset_liability_ratio], kdeTrue, bins30) plt.title(资产负债率分布) plt.xlabel(资产负债率) plt.subplot(2, 2, 3) sns.scatterplot(xasset_liability_ratio, yroe_capped, hueis_st, datadf, alpha0.6) plt.title(资产负债率 vs ROE (按ST状态着色)) plt.xlabel(资产负债率) plt.ylabel(ROE (盖帽后)) # 3. 按行业分析ST比例 plt.subplot(2, 2, 4) # 计算各行业ST比例 industry_st_rate {} for col in df.columns: if col.startswith(ind_): industry_name col.replace(ind_, ) st_rate df[df[col]1][is_st].mean() industry_st_rate[industry_name] st_rate st_rate_series pd.Series(industry_st_rate).sort_values(ascendingFalse) st_rate_series.plot(kindbarh, colorlightgreen) plt.title(各行业ST公司比例) plt.xlabel(ST比例) plt.tight_layout() plt.show() # 4. 相关性热图数值特征 numeric_features [net_profit, asset_liability_ratio, current_ratio, roe_capped, total_asset_turnover, profit_margin] corr_matrix df[numeric_features [is_st]].corr() plt.figure(figsize(10, 8)) sns.heatmap(corr_matrix, annotTrue, fmt.2f, cmapcoolwarm, center0) plt.title(数值特征与目标变量相关性热图) plt.show()通过图表我们可以直观看到ST公司占少数资产负债率与ROE似乎存在一定关系不同行业的ST风险比例不同资产负债率与is_st呈现正相关符合常识而ROE、总资产周转率与is_st呈负相关。4.4 构建与评估预测模型现在我们进入机器学习建模环节。# 1. 准备特征(X)和目标变量(y) # 选择用于建模的特征列 feature_columns [asset_liability_ratio, current_ratio, roe_capped, total_asset_turnover, profit_margin] feature_columns.extend([col for col in df.columns if col.startswith(ind_)]) # 加入行业哑变量 X df[feature_columns] y df[is_st] print(f特征矩阵X的形状{X.shape}) print(f目标变量y的形状{y.shape}) # 2. 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42, stratifyy) print(f训练集大小{X_train.shape} 测试集大小{X_test.shape}) print(f训练集ST比例{y_train.mean():.3f} 测试集ST比例{y_test.mean():.3f}) # 3. 特征标准化对逻辑回归等基于距离的模型很重要 scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) # 4. 训练逻辑回归模型 print(\n *50) print(逻辑回归模型) print(*50) lr_model LogisticRegression(random_state42, max_iter1000, class_weightbalanced) # 使用class_weight处理不平衡 lr_model.fit(X_train_scaled, y_train) y_pred_lr lr_model.predict(X_test_scaled) y_pred_proba_lr lr_model.predict_proba(X_test_scaled)[:, 1] # 预测为ST的概率 print(准确率, accuracy_score(y_test, y_pred_lr)) print(\n分类报告) print(classification_report(y_test, y_pred_lr, target_names[非ST, ST])) print(AUC分数, roc_auc_score(y_test, y_pred_proba_lr)) # 5. 训练随机森林模型 print(\n *50) print(随机森林模型) print(*50) rf_model RandomForestClassifier(n_estimators100, random_state42, class_weightbalanced) rf_model.fit(X_train, y_train) # 树模型通常不需要标准化 y_pred_rf rf_model.predict(X_test) y_pred_proba_rf rf_model.predict_proba(X_test)[:, 1] print(准确率, accuracy_score(y_test, y_pred_rf)) print(\n分类报告) print(classification_report(y_test, y_pred_rf, target_names[非ST, ST])) print(AUC分数, roc_auc_score(y_test, y_pred_proba_rf)) # 6. 模型对比ROC曲线 fpr_lr, tpr_lr, _ roc_curve(y_test, y_pred_proba_lr) fpr_rf, tpr_rf, _ roc_curve(y_test, y_pred_proba_rf) plt.figure(figsize(8,6)) plt.plot(fpr_lr, tpr_lr, labelfLogistic Regression (AUC{roc_auc_score(y_test, y_pred_proba_lr):.3f})) plt.plot(fpr_rf, tpr_rf, labelfRandom Forest (AUC{roc_auc_score(y_test, y_pred_proba_rf):.3f})) plt.plot([0, 1], [0, 1], k--, labelRandom Guess) plt.xlabel(False Positive Rate) plt.ylabel(True Positive Rate (Recall)) plt.title(ROC曲线对比) plt.legend() plt.grid(True) plt.show() # 7. 特征重要性分析随机森林 feature_importance pd.DataFrame({ feature: feature_columns, importance: rf_model.feature_importances_ }).sort_values(importance, ascendingFalse) plt.figure(figsize(10, 6)) sns.barplot(ximportance, yfeature, datafeature_importance.head(10), paletteviridis) plt.title(随机森林模型特征重要性 Top 10) plt.xlabel(重要性得分) plt.tight_layout() plt.show() print(特征重要性排序) print(feature_importance)4.5 结果解读与商业洞察运行完模型后我们需要解读结果模型性能从分类报告和ROC曲线看随机森林模型在AUC和召回率对ST类的识别能力上可能略优于逻辑回归。但逻辑回归的模型更简单可解释性更强。关键指标解读精确率在所有被模型预测为ST的公司中真正是ST的比例。这个值高说明模型的“误伤”少。召回率在所有真实的ST公司中被模型成功找出来的比例。这个值高说明模型的“漏网之鱼”少。F1-score精确率和召回率的调和平均数是综合衡量指标。在我们的不平衡数据集中关注ST类的F1-score更重要。特征重要性随机森林显示asset_liability_ratio资产负债率和roe_capped净资产收益率是最重要的两个预测因子。这完全符合财务常识——高负债、低盈利的公司风险更高。profit_margin是否盈利也是一个强信号。商业建议基于模型可以构建一个初步的财务风险预警系统。对于资产负债率超过70%、ROE连续为负的公司应予以重点关注。模型给出的预测概率可以作为风险评分辅助投资决策或内部审计。5. 常见问题与排查思路在实践过程中你可能会遇到以下问题问题现象可能原因解决思路ImportError: No module named ‘pandas’Python环境未安装所需库或不在正确的环境中。1. 确认已使用pip install pandas安装。2. 如果你使用Anaconda确认激活了正确的环境 (conda activate your_env)。3. 在Jupyter中尝试!pip install pandas。数据读取失败编码错误CSV文件包含中文或特殊字符默认编码不对。使用pd.read_csv(‘file.csv’, encoding‘gbk’或’utf-8-sig’)指定编码。模型准确率很高如99%但召回率为0数据泄露或类别极度不平衡导致模型只会预测多数类。1. 检查特征中是否包含了未来信息或目标变量的直接映射。2. 使用class_weight‘balanced’参数。3. 使用过采样如SMOTE或欠采样技术。逻辑回归模型不收敛警告特征尺度差异大或迭代次数不足。1.务必进行特征标准化使用StandardScaler。2. 增加max_iter参数如1000或更大。可视化图表中文显示为方框matplotlib默认字体不支持中文。在代码开头添加plt.rcParams[‘font.sans-serif’] [‘SimHei’]plt.rcParams[‘axes.unicode_minus’] False独热编码后特征维度爆炸某个分类特征类别过多如城市。1. 考虑将不重要的类别归为“其他”。2. 使用目标编码等其它编码方式。ValueError: Input contains NaN训练数据中存在缺失值。在训练前使用X_train.isnull().sum()检查并处理缺失值。6. 最佳实践与报告撰写建议完成代码分析只是第一步将工作整理成一份专业的报告同样重要。6.1 数据分析最佳实践版本控制使用Git管理你的代码和Notebook特别是数据处理步骤确保结果可复现。函数化与模块化将数据清洗、特征工程等步骤封装成函数提高代码可读性和复用性。交叉验证在最终评估前使用cross_val_score进行交叉验证以获得更稳健的性能估计。处理不平衡数据除了class_weight可以深入研究SMOTE、ADASYN等过采样算法。模型解释对于逻辑回归查看系数对于树模型使用SHAP或LIME库进行更细致的局部解释。6.2 期末实践报告撰写结构建议一份好的报告不仅是代码的堆砌更是逻辑的展现。封面与摘要标题、姓名、学号、课程、日期。摘要用200-300字概括项目目标、方法、主要发现和结论。引言阐述研究背景数据科学在财务领域的应用、项目意义及核心目标。数据说明描述数据来源、字段含义、数据规模、初步的质量评估缺失、异常情况。方法论清晰说明采用的数据清洗步骤、特征工程方法、选择的机器学习模型及其原理简介、模型评估指标。实验过程与结果分析这是核心。数据分析部分配上关键图表分布图、散点图、热图并解释你观察到了什么现象。建模部分展示模型训练代码关键部分、模型在测试集上的性能指标准确率、精确率、召回率、F1、AUC最好用表格对比不同模型。结果解释分析特征重要性说明哪些财务指标对预测影响最大并与财务理论相印证。讨论分析模型的优缺点如过拟合风险、可解释性、项目局限性数据模拟、特征有限、未来改进方向引入更多数据、尝试深度学习模型。结论总结项目是否达成了最初的目标并给出基于分析结果的一到两条核心商业建议。参考文献列出引用的数据来源、算法库文档、相关学术或实践文章。附录附上完整的、可运行的Jupyter Notebook代码或提供GitHub链接。6.3 代码与报告整合技巧在Jupyter Notebook中使用Markdown单元格撰写详细的文字分析将代码、输出结果和文字叙述无缝衔接。将生成的图表保存为高分辨率图片plt.savefig(‘images/roe_dist.png’, dpi300, bbox_inches‘tight’)便于插入到最终的Word或PDF报告中。可以使用nbconvert工具将Notebook直接转换为HTML或PDF报告。通过这个完整的项目你不仅掌握了使用Python进行数据分析与机器学习建模的实战技能更关键的是理解了从商业问题出发到数据、模型最终回归商业洞察的完整闭环思维。这套方法论可以迁移到任何你感兴趣的领域无论是客户流失预测、销售 forecasting 还是风险控制。