ARTICLE DETAIL

资讯详情

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

Python数据分析与挖掘实训数据全流程实战指南

Python数据分析与挖掘实训数据全流程实战指南 简介这份实训数据包面向正在学习Python数据分析与挖掘的在校学生与转行开发者围绕真实业务场景提供可动手练习的数据素材帮助读者把数据清洗、探索分析、特征工程与机器学习建模等环节串联成完整实践链路。包内共17个文件以csv数据表为主辅以xlsx、xls表格和sql建表脚本压缩包约112.9MB覆盖用户信息、消费记录、商品销售、内容浏览日志等典型数据集可直接用于Pandas读取、可视化绘图与Scikit-Learn建模练习。目前已有395人学习下载。资源按章节组织从基础语法与数据预处理到描述性统计、数据导入导出、特征选择与编码再到线性回归、决策树、随机森林、聚类及神经网络等模型训练与评估读者可据此复现完整分析流程积累数据驱动决策的实战经验。1. 拿到一个实训数据压缩包先别急着解压很多人拿到「Python数据分析与挖掘实战_实训数据.zip」这类压缩包第一反应是双击解压然后打开 Jupyter Notebook 开始pd.read_csv。我见过太多人卡在这一步编码报错、路径找不到、字段名带空格、日期列全是字符串。问题不在代码在于你还没搞清楚这个压缩包里到底装了什么。这个标题指向的是一套完整的实训数据资产通常包含多个 CSV 或 Excel 文件覆盖分类、回归、聚类、关联规则等典型挖掘任务。它解决的核心问题是让你在一个相对干净的数据集上把 Python 数据分析与挖掘的全流程跑通一遍而不是对着泰坦尼克号这种被讲烂了的数据集反复调参。适合谁适合已经会写 Python 基础语法、但还没完整走过「加载→清洗→特征→建模→评估」这条链路的人。也适合需要快速验证某个算法在真实数据上表现的从业者。2. 解压之后第一件事用 Python 做数据资产盘点2.1 为什么不能靠肉眼扫一遍文件夹压缩包解压后你面对的可能是一堆命名混乱的文件data1.csv、train_final_v2.csv、用户行为数据.xlsx。肉眼扫一遍只能看个大概真正要动手之前必须用代码把每个文件的形状、字段类型、缺失情况、重复行数全部拉出来。这一步不做后面清洗就是盲人摸象。我一般会写一个盘点脚本遍历目录下所有 CSV 和 Excel输出一张汇总表。这样你一眼就能看出哪个文件是主表、哪个是维度表、哪个可能是脏数据。import os import pandas as pd from pathlib import Path # 指向解压后的根目录 root Path(./实训数据) # 收集所有数据文件 files [] for ext in [*.csv, *.xlsx, *.xls]: files.extend(root.rglob(ext)) summary [] for f in files: try: if f.suffix .csv: # 先尝试 utf-8失败再换 gbk try: df pd.read_csv(f, encodingutf-8, nrows5000) except UnicodeDecodeError: df pd.read_csv(f, encodinggbk, nrows5000) else: df pd.read_excel(f, nrows5000) summary.append({ 文件: f.name, 行数(前5000): len(df), 列数: df.shape[1], 字段: , .join(df.columns[:8].tolist()), 缺失列数: df.isnull().any().sum() }) except Exception as e: summary.append({文件: f.name, 行数(前5000): f读取失败: {e}}) print(pd.DataFrame(summary).to_string(indexFalse))这段代码的逻辑很直接递归找文件逐个尝试读取遇到编码问题自动切换。nrows5000是为了快速预览避免大文件卡住。输出结果里重点看三列行数、列数、缺失列数。如果某个文件行数特别大但列数很少可能是日志类数据如果缺失列数接近总列数说明这个文件质量堪忧需要单独处理。参数说明encoding是中文数据最常见的坑utf-8 读不了就换 gbk再读不了就考虑encoding_errorsignore但那样会丢字符慎用。rglob会递归子目录确保不漏文件。2.2 字段类型和唯一值检查别让 ID 列混进特征盘点完文件下一步是看每个字段的类型和唯一值数量。这一步的目的是区分三类列ID 类、类别类、数值类。ID 类列比如用户编号、订单号唯一值数量接近行数这种列绝对不能进模型否则就是标签泄露。类别类列唯一值少适合做独热编码或目标编码。数值类列要看分布偏态严重的后面得做变换。# 以主表为例假设叫 main.csv df pd.read_csv(./实训数据/main.csv, encodingutf-8) col_info [] for col in df.columns: nunique df[col].nunique() dtype df[col].dtype missing df[col].isnull().sum() col_info.append({ 字段: col, 类型: str(dtype), 唯一值数: nunique, 缺失数: missing, 缺失率: f{missing/len(df):.2%} }) info_df pd.DataFrame(col_info).sort_values(唯一值数, ascendingFalse) print(info_df.to_string(indexFalse))逻辑说明nunique()算唯一值isnull().sum()算缺失数。排序后唯一值数最高的几列大概率是 ID直接标记为待删除。缺失率超过 60% 的列除非业务上极其重要否则也建议先放一边。这一步做完你手里就有一张「字段体检表」后面每一步清洗都有据可依。3. 数据清洗与特征处理把脏数据变成能喂给模型的东西3.1 缺失值填充的三种策略和选择依据缺失值处理没有万能公式得看字段含义和缺失比例。我一般分三种情况缺失率低于 5% 且是数值列用中位数填充缺失率 5% 到 30% 之间用模型预测填充或者单独标记为「缺失」类别缺失率超过 30%直接删列除非业务方明确说这个字段必须保留。# 数值列中位数填充 num_cols df.select_dtypes(include[float64, int64]).columns for col in num_cols: if df[col].isnull().sum() / len(df) 0.05: df[col] df[col].fillna(df[col].median()) # 类别列填充为 Unknown cat_cols df.select_dtypes(include[object]).columns for col in cat_cols: df[col] df[col].fillna(Unknown) # 缺失率超过 30% 的列直接删除 threshold 0.3 drop_cols [col for col in df.columns if df[col].isnull().sum() / len(df) threshold] df df.drop(columnsdrop_cols) print(f删除列: {drop_cols})参数说明中位数比均值抗异常值适合大多数业务数据。类别列填Unknown而不是众数是为了保留「缺失」这个信息本身有时候缺失就是一种信号。threshold0.3可以根据实际情况调整但不要超过 0.5否则删太多列模型没法跑。3.2 类别编码独热编码和目标编码怎么选类别列不能直接进模型必须编码。独热编码适合唯一值少于 15 个的列目标编码适合高基数类别列比如城市、商品 ID。独热编码的坑是维度爆炸目标编码的坑是过拟合。我一般先看唯一值数量少于 15 走独热多于 15 走目标编码并且目标编码必须用交叉验证的方式计算否则标签泄露。from sklearn.preprocessing import OneHotEncoder import category_encoders as ce # 低基数类别列独热编码 low_card_cols [col for col in cat_cols if df[col].nunique() 15] df pd.get_dummies(df, columnslow_card_cols, drop_firstTrue) # 高基数类别列目标编码需要指定目标列 high_card_cols [col for col in cat_cols if df[col].nunique() 15] if high_card_cols: target_col label # 替换成你的目标列名 encoder ce.TargetEncoder(colshigh_card_cols, smoothing10) df encoder.fit_transform(df, df[target_col])逻辑说明drop_firstTrue是为了避免独热编码的共线性问题。smoothing10是目标编码的平滑参数值越大越保守过拟合风险越低但信息损失也越多。常见做法是 5 到 20 之间调。注意目标编码必须在训练集上 fit再 transform 测试集不能全量 fit。3.3 数值列标准化和异常值处理数值列量纲不统一树模型无所谓但线性模型和神经网络必须标准化。异常值处理要看业务如果是传感器数据异常值可能是真实故障信号不能随便删如果是用户行为数据极端值可能是爬虫需要截断。from sklearn.preprocessing import StandardScaler # 标准化 scaler StandardScaler() num_cols_final df.select_dtypes(include[float64, int64]).columns df[num_cols_final] scaler.fit_transform(df[num_cols_final]) # 异常值截断超过 3 倍标准差的截断到边界 for col in num_cols_final: mean df[col].mean() std df[col].std() lower mean - 3 * std upper mean 3 * std df[col] df[col].clip(lower, upper)参数说明StandardScaler是零均值单位方差适合大多数场景。3 * std是经验值也可以用 IQR 的 1.5 倍。clip是截断而不是删除保留样本量的同时控制极端值影响。4. 建模与评估从基线模型到调参的完整链路4.1 先跑一个基线模型别一上来就上 XGBoost很多人拿到数据直接上 XGBoost 调参结果跑了半天不知道问题出在数据还是模型。我的习惯是先跑逻辑回归或决策树作为基线看 AUC 或 F1 大概在什么水平。如果基线模型 AUC 只有 0.55说明特征工程有问题换什么模型都救不了。from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report, roc_auc_score # 假设目标列叫 label X df.drop(columns[label]) y df[label] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) baseline LogisticRegression(max_iter1000) baseline.fit(X_train, y_train) y_pred baseline.predict(X_test) y_prob baseline.predict_proba(X_test)[:, 1] print(classification_report(y_test, y_pred)) print(fAUC: {roc_auc_score(y_test, y_prob):.4f})逻辑说明stratifyy保证训练集和测试集类别比例一致类别不平衡时必加。max_iter1000防止收敛警告。基线模型 AUC 低于 0.6 就要回头检查特征高于 0.75 说明数据本身信号强可以上复杂模型。4.2 树模型调参GridSearch 和 Optuna 的取舍基线跑通后上 LightGBM 或 XGBoost。调参方法有两种GridSearch 适合参数少、算力有限的情况Optuna 适合参数多、想快速找最优的情况。我一般先用 GridSearch 粗调再用 Optuna 细调。import lightgbm as lgb from sklearn.model_selection import GridSearchCV param_grid { num_leaves: [31, 63, 127], learning_rate: [0.05, 0.1], n_estimators: [100, 300], min_child_samples: [10, 20] } lgb_model lgb.LGBMClassifier(objectivebinary, random_state42) grid GridSearchCV( lgb_model, param_grid, cv3, scoringroc_auc, n_jobs-1, verbose1 ) grid.fit(X_train, y_train) print(f最佳参数: {grid.best_params_}) print(f最佳 AUC: {grid.best_score_:.4f})参数说明num_leaves控制树复杂度越大越容易过拟合。learning_rate和n_estimators要配合调学习率低就需要更多树。min_child_samples防止叶子节点样本太少。cv3是折数数据量大可以降到 3数据量小用 5。4.3 交叉验证和模型融合的实操细节单模型调完想再提升就上交叉验证和融合。交叉验证用 StratifiedKFold融合用简单加权平均或 Stacking。注意融合的前提是模型之间相关性低如果两个模型都是 LightGBM融合提升有限。from sklearn.model_selection import StratifiedKFold import numpy as np skf StratifiedKFold(n_splits5, shuffleTrue, random_state42) oof_preds np.zeros(len(X_train)) test_preds np.zeros(len(X_test)) for fold, (train_idx, val_idx) in enumerate(skf.split(X_train, y_train)): X_tr, X_val X_train.iloc[train_idx], X_train.iloc[val_idx] y_tr, y_val y_train.iloc[train_idx], y_train.iloc[val_idx] model lgb.LGBMClassifier(**grid.best_params_, random_state42) model.fit(X_tr, y_tr) oof_preds[val_idx] model.predict_proba(X_val)[:, 1] test_preds model.predict_proba(X_test)[:, 1] / skf.n_splits print(fOOF AUC: {roc_auc_score(y_train, oof_preds):.4f})逻辑说明OOF 预测是拿来做融合特征的不能直接用训练集预测。test_preds是五折模型对测试集的平均预测比单模型稳定。这一步做完你就有了一个可靠的提交结果。5. 避坑与排查实训数据里最容易翻车的五个地方5.1 编码问题导致中文列名变乱码现象pd.read_csv读进来列名全是\xe7\x94\xa8\xe6\x88\xb7这种。原因文件是 GBK 编码默认用 UTF-8 读。解决先试encodinggbk再试encodinggb18030还不行就用chardet检测。5.2 日期列被当成字符串排序和计算全错现象df[date].max()返回的是字符串比较结果不是真实最大日期。原因读取时没指定parse_dates。解决pd.read_csv(..., parse_dates[date])或者读完后pd.to_datetime(df[date], errorscoerce)。5.3 训练集和测试集分布不一致导致线上崩盘现象本地交叉验证 AUC 0.85换一批数据掉到 0.6。原因训练集和测试集的时间范围或用户群体不同。解决按时间切分而不是随机切分或者用对抗验证检查分布差异。5.4 目标编码在测试集上用了全量数据现象模型在训练集上 AUC 0.99测试集 0.5。原因目标编码时用了全量数据的标签。解决目标编码必须在训练集上 fit测试集只 transform或者用 K 折方式计算。5.5 特征重要性全是 ID 列模型学了个寂寞现象LightGBM 特征重要性排名第一的是user_id。原因ID 列没删模型直接记住了每个 ID 的标签。解决建模前把所有唯一值接近行数的列删掉或者用df.nunique() / len(df) 0.9自动过滤。6. 进阶技巧用 SHAP 做特征归因和业务解释模型跑通只是第一步业务方要的是「为什么这个用户被预测为流失」。SHAP 是目前最可靠的特征归因工具它能量化每个特征对单个预测的贡献。我一般用shap.TreeExplainer对 LightGBM 做解释输出 summary plot 和 dependence plot。import shap explainer shap.TreeExplainer(grid.best_estimator_) shap_values explainer.shap_values(X_test) # 全局特征重要性 shap.summary_plot(shap_values, X_test, plot_typebar) # 单个样本解释 shap.force_plot( explainer.expected_value, shap_values[0, :], X_test.iloc[0, :], matplotlibTrue )逻辑说明shap_values的 shape 是(样本数, 特征数)每个值代表该特征对预测结果的推动方向。summary_plot的 bar 类型展示全局重要性beeswarm 类型展示每个样本的贡献分布。force_plot适合给业务方看单个案例红色推高预测蓝色拉低预测。参数说明TreeExplainer对树模型是精确解速度快。如果模型是神经网络换DeepExplainer但速度慢很多。X_test不要太大几千行就够否则图太密看不清。一个我踩过的坑SHAP 值的方向和特征原始值的方向不一定一致。比如「年龄」的 SHAP 值随年龄增大而增大但业务上年龄越大流失率越低这时候要看 dependence plot 确认单调性不能只看 summary plot 的排序。另一个技巧把 SHAP 值和业务规则结合。如果发现「最近一次登录间隔」的 SHAP 值在超过 30 天后急剧上升那就可以直接把这个阈值写进运营规则不用等模型预测。模型是黑匣子SHAP 是手电筒照到哪里哪里就有解释。我现在的习惯是每次模型上线前必跑一遍 SHAP把 top 10 特征和业务方过一遍。如果出现业务方完全不理解的字段要么是特征工程有问题要么是数据泄露。这个习惯帮我省了很多后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表