简介这份实训数据包面向正在学习Python数据分析与挖掘的在校学生与转行自学者围绕数据清洗、探索性分析、特征工程到机器学习建模的完整链路提供配套练习素材帮助读者在真实数据集上巩固课堂知识、完成课程实验或毕业设计。压缩包共17个文件约112.9MB以csv数据表为主辅以xlsx、xls表格和sql建表脚本覆盖用户信息、消费记录、商品销售、访问日志等多类业务场景可直接用于Pandas读取、可视化绘图与Scikit-Learn建模练习。目前已有395人学习下载。资源按章节组织从基础语法与数据导入导出到缺失值处理、描述性统计、特征选择与编码再到线性回归、决策树、聚类及神经网络等模型训练评估形成由浅入深的学习路径适合边学边练、逐步积累数据驱动决策的实战经验。1. 拿到一个实训数据压缩包先别急着解压很多人拿到实训数据.zip这类文件第一反应是双击解压、打开 Jupyter、pd.read_csv一把梭然后被编码错误、路径错乱、字段含义不明三连击打回原形。我带过几届实训见过太多人卡在“数据在哪、长什么样、字段啥意思”这一步代码还没写几行时间已经过去一半。Python 数据分析与挖掘实战的核心从来不是模型多花哨而是你能不能把一个来路不明的压缩包变成一张干净、可解释、能喂给算法或可视化工具的表。这篇笔记就围绕这个压缩包展开怎么在本地把环境配好、怎么把数据读进来、怎么判断它适合做描述性分析还是分类聚类、以及那些只有踩过才知道的坑。适合刚学完 Python 基础语法、准备做第一个完整数据分析项目的人也适合需要快速复现一套实训流程的助教或自学者。下面所有操作都基于你本地已经有一个实训数据.zip内容未知我们一步步把它拆开看。2. 环境与数据入口从 python 安装到第一次成功读取2.1 选 Anaconda 还是裸 python 安装教程里的方案网上搜“python安装教程”会出来一堆让你去官网下 exe 再配 PATH 的流程但做数据分析与挖掘实战我一般直接推荐 Anaconda 或 Miniconda。原因很简单pandas、numpy、scikit-learn、matplotlib这些包在 Windows 上裸装经常卡在编译依赖而 conda 能一次性把二进制包和解释器版本对齐。如果你已经装了 python也不想再下几个 G 的发行版那就用venv加 pip但务必把 pip 源换成国内镜像否则装scikit-learn时你会以为电脑死机了。先确认你当前环境里有没有 Python以及版本是否在 3.8 以上。打开终端或 PowerShellpython --version # 如果输出 Python 3.8.x 及以上继续如果提示找不到命令先去装 Miniconda接着建一个专门用于这次实训的虚拟环境避免和你系统里其他项目的包版本打架conda create -n shixun python3.10 -y conda activate shixun # 如果你用 venv则换成 python -m venv shixun source shixun/bin/activateWindows 用 shixun\Scripts\activate环境激活后一次性把数据分析四件套和挖掘常用库装好pip install pandas numpy matplotlib scikit-learn openpyxl xlrd -i https://pypi.tuna.tsinghua.edu.cn/simple这里openpyxl和xlrd是为了应对压缩包里可能出现的 Excel 文件scikit-learn覆盖大部分基础挖掘算法。参数-i指定镜像源不写也能装但速度看运气。装完后用一行命令验证import pandas as pd, numpy as np, sklearn print(pd.__version__, np.__version__, sklearn.__version__)只要不报ModuleNotFoundError环境就算立住了。这一步的坑在于很多人装完包后在错误的解释器里跑代码比如 VSCode 右下角选的还是系统 Python结果import pandas失败。解决办法是 VSCode 里按CtrlShiftP输入Python: Select Interpreter选中你刚建的shixun环境。2.2 解压前先看压缩包结构别直接 extractall拿到实训数据.zip不要写 Python 脚本去解压先用系统命令看一眼里面有什么。Windows 上用tar -tf也能列 zip 内容Win10 以上自带 tarLinux/macOS 直接用unzip -lunzip -l 实训数据.zip # 输出会列出所有文件名和目录层级注意看有没有中文文件名、有没有 __MACOSX 这种垃圾目录这一步能帮你判断三件事数据是 CSV 还是 Excel 还是 JSON有没有嵌套文件夹有没有多个版本的文件比如train.csv和train_fixed.csv。我见过最坑的一个压缩包里面套了三层目录每层都有一个同名 CSV内容还不一样。如果你直接extractall再glob很可能读到错的那个。确认结构后用 Python 解压到指定目录并统一转成 UTF-8 文件名避免后续路径里带中文或空格导致pd.read_csv报FileNotFoundErrorimport zipfile, os, shutil zip_path 实训数据.zip extract_dir shixun_data # 如果目录已存在先清掉保证每次都是干净解压 if os.path.exists(extract_dir): shutil.rmtree(extract_dir) os.makedirs(extract_dir) with zipfile.ZipFile(zip_path, r) as z: # 过滤掉 __MACOSX 和隐藏文件 members [m for m in z.namelist() if not m.startswith(__MACOSX) and not m.startswith(.)] z.extractall(extract_dir, membersmembers) # 打印解压后的文件树方便确认 for root, dirs, files in os.walk(extract_dir): level root.replace(extract_dir, ).count(os.sep) indent * 2 * level print(f{indent}{os.path.basename(root)}/) for f in files: print(f{indent} {f})逻辑说明namelist()拿到压缩包内所有条目过滤掉 macOS 自动生成的元数据目录extractall的members参数只解压我们筛选后的文件。参数extract_dir你可以改成任何英文路径但别用中文否则某些库读路径时会出玄学问题。跑完这段你就能看到数据到底长什么样再决定下一步用read_csv还是read_excel。2.3 第一次读取用 nrows 和 encoding 试探别全量硬读假设文件树显示有一个data.csv路径是shixun_data/data.csv。直接pd.read_csv可能会遇到编码错误或分隔符不对。我的习惯是先读前 5 行探路import pandas as pd file_path shixun_data/data.csv # 先试 utf-8失败再换 gbk这是中文数据最常见的两种编码 try: df_head pd.read_csv(file_path, nrows5, encodingutf-8) except UnicodeDecodeError: df_head pd.read_csv(file_path, nrows5, encodinggbk) print(df_head) print(列名, df_head.columns.tolist()) print(形状前5行, df_head.shape)nrows5只读前 5 行速度快不会因为文件几个 G 而卡死。encoding参数先 utf-8 后 gbk 是血泪经验很多从 Excel 导出的 CSV 默认 gbk你硬用 utf-8 读会直接抛异常。如果列名里带Unnamed: 0说明原始文件有索引列读全量时加index_col0去掉。确认列名和分隔符正常后再读全量df pd.read_csv(file_path, encodingutf-8) # 或 gbk print(df.info()) print(df.describe(includeall))info()看每列的非空数量和 dtypedescribe(includeall)看数值列统计和类别列频次。这两条命令能让你在 30 秒内判断数据质量有没有大量缺失、数值列是不是被读成了 object、类别列有没有异常值。到这里数据入口就算打通了。3. 数据清洗与特征初探把脏表变成能挖的表3.1 缺失值、重复值和异常值的处理顺序拿到df之后别急着画图或跑模型。先处理三类脏数据缺失、重复、异常。顺序很重要我一般先删完全重复的行再处理缺失最后处理异常值。因为重复行会干扰缺失统计而异常值可能在缺失填充后被掩盖。# 1. 删完全重复的行 before df.shape[0] df df.drop_duplicates() print(f删除重复行{before - df.shape[0]} 条) # 2. 查看缺失情况 missing df.isnull().sum() missing_pct (missing / len(df) * 100).round(2) missing_df pd.DataFrame({缺失数: missing, 缺失比例%: missing_pct}) print(missing_df[missing_df[缺失数] 0].sort_values(缺失比例%, ascendingFalse))缺失处理策略看比例低于 5% 的数值列直接fillna(df[col].median())类别列用众数5% 到 30% 之间的考虑用模型预测填充或单独标记为“未知”超过 30% 的列除非业务上极其重要否则直接drop。这里没有绝对标准但实训数据通常缺失不会太夸张中位数填充足够。异常值用 IQR 法快速筛def iqr_outlier_bounds(series): q1, q3 series.quantile(0.25), series.quantile(0.75) iqr q3 - q1 return q1 - 1.5 * iqr, q3 1.5 * iqr num_cols df.select_dtypes(include[number]).columns for col in num_cols: low, high iqr_outlier_bounds(df[col].dropna()) outliers df[(df[col] low) | (df[col] high)] if len(outliers) 0: print(f{col}: {len(outliers)} 个异常值范围 [{low:.2f}, {high:.2f}])逻辑说明IQR 法不假设正态分布对偏态数据也稳。参数1.5是经典系数想更宽松可以改 3.0。发现异常值后不要无脑删先看是不是录入错误比如年龄 200 岁是则修正或删除如果是真实极端值比如高收入人群保留并考虑做对数变换。3.2 用 pandas 做描述性分析groupby 和 pivot_table 的取舍清洗完先做描述性分析。很多人只会df.describe()但实训数据往往需要按类别拆分看分布。groupby适合做聚合统计pivot_table适合做交叉表。举个例子假设数据里有城市和销售额两列# groupby按城市算销售额均值和总和 city_stats df.groupby(城市)[销售额].agg([mean, sum, count]).reset_index() city_stats.columns [城市, 销售额均值, 销售额总和, 样本数] print(city_stats.sort_values(销售额总和, ascendingFalse).head(10)) # pivot_table城市 × 产品类别的销售额交叉表 pivot pd.pivot_table(df, values销售额, index城市, columns产品类别, aggfuncsum, fill_value0) print(pivot.head())groupby的agg可以一次传多个函数reset_index把分组键变回列方便后续导出。pivot_table的fill_value0把缺失组合填 0避免 NaN 干扰可视化。选哪个取决于你要回答的问题如果只是“每个城市表现如何”用 groupby如果要看“城市和产品类别的交互”用 pivot_table。这一步的输出可以直接喂给 matplotlib 画柱状图或热力图但本文不展开画图重点在数据本身。3.3 特征工程从原始列里榨出可用变量实训数据挖掘部分通常需要你构造特征。常见操作日期列拆成年月日、类别列做 one-hot、数值列做分箱。以日期为例# 假设有一列 交易时间格式是字符串 df[交易时间] pd.to_datetime(df[交易时间], errorscoerce) df[年] df[交易时间].dt.year df[月] df[交易时间].dt.month df[日] df[交易时间].dt.day df[星期] df[交易时间].dt.dayofweek # 0周一 # 数值分箱把年龄分成青年/中年/老年 df[年龄段] pd.cut(df[年龄], bins[0, 30, 50, 100], labels[青年, 中年, 老年]) # 类别 one-hot df pd.get_dummies(df, columns[城市], prefix城市, drop_firstTrue)pd.to_datetime的errorscoerce把无法解析的日期变成 NaT避免整列报错。pd.cut的bins和labels要按业务定别硬套。get_dummies的drop_firstTrue去掉一个哑变量避免共线性做线性回归时尤其要注意。这些特征构造完后你的df就从原始表变成了可以喂给scikit-learn的矩阵。注意one-hot 后列数会膨胀如果类别太多比如超过 50 个考虑用目标编码或频率编码替代。4. 挖掘建模从聚类到分类的最小可跑通路径4.1 无监督先跑 KMeans确定簇数的肘部法和轮廓系数拿到特征矩阵后如果数据没有标签先做聚类探索。KMeans 是最容易上手的但难点在确定n_clusters。我一般同时看肘部法inertia和轮廓系数from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler from sklearn.metrics import silhouette_score # 选数值特征列标准化 feature_cols [年龄, 销售额, 交易时间] # 按你实际列名改 X df[feature_cols].dropna() scaler StandardScaler() X_scaled scaler.fit_transform(X) inertias, silhouettes [], [] k_range range(2, 11) for k in k_range: km KMeans(n_clustersk, random_state42, n_init10) labels km.fit_predict(X_scaled) inertias.append(km.inertia_) silhouettes.append(silhouette_score(X_scaled, labels)) for k, inertia, sil in zip(k_range, inertias, silhouettes): print(fk{k}, inertia{inertia:.2f}, silhouette{sil:.3f})逻辑说明StandardScaler把不同量纲的特征拉到同一尺度否则销售额大的列会主导距离计算。n_init10让 KMeans 用不同初始化跑 10 次取最优避免局部最优。inertia越小簇越紧但会随 k 增大单调下降所以看拐点silhouette越接近 1 越好一般选轮廓系数最高的 k同时结合肘部拐点。如果两个指标冲突优先选轮廓系数高的因为肘部法有时拐点不明显。4.2 有监督分类用 train_test_split 和随机森林跑通基线如果数据有标签列比如是否流失那就做分类。别一上来就调参先跑一个随机森林基线看特征重要性from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix # 假设标签列叫 标签 X df.drop(columns[标签]) y df[标签] # 类别特征先 one-hot数值特征保持 X pd.get_dummies(X, drop_firstTrue) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42, stratifyy) rf RandomForestClassifier(n_estimators100, random_state42, class_weightbalanced) rf.fit(X_train, y_train) y_pred rf.predict(X_test) print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred)) # 特征重要性 importances pd.Series(rf.feature_importances_, indexX.columns).sort_values(ascendingFalse) print(importances.head(10))stratifyy保证训练集和测试集里标签比例一致类别不平衡时必加。class_weightbalanced自动给少数类更高权重比手动过采样省事。classification_report看 precision、recall、f1别只看 accuracy不平衡数据下 accuracy 会骗人。特征重要性排前几的列就是你后续做特征筛选或业务解释的重点。如果效果太差再考虑调n_estimators、max_depth或换 GradientBoosting。4.3 模型评估与交叉验证别用一次 train_test_split 定生死单次划分的评估结果波动很大尤其是小数据集。我习惯用 5 折交叉验证看稳定性from sklearn.model_selection import cross_val_score scores cross_val_score(rf, X, y, cv5, scoringf1_weighted) print(f5折F1{scores}) print(f均值{scores.mean():.3f}标准差{scores.std():.3f})cv5把数据分 5 份轮流做验证scoring选f1_weighted兼顾类别不平衡。标准差大于 0.05 说明模型不稳定可能是数据量太小或特征噪声大。这时候别急着上深度学习先回去检查特征工程和缺失处理。交叉验证的耗时是单次划分的 5 倍但能帮你避免“调参调到过拟合”的翻车现场。5. 避坑与排查实训数据挖掘里最容易翻车的 5 个点5.1 编码错误反复出现换了 gbk 还是乱码现象pd.read_csv报UnicodeDecodeError换成 gbk 后部分行仍然乱码。原因文件可能是 utf-8-sig带 BOM或混合编码。解决先试encodingutf-8-sig再试gb18030比 gbk 覆盖更全最后用chardet检测import chardet with open(shixun_data/data.csv, rb) as f: print(chardet.detect(f.read(10000)))拿到置信度最高的编码再读。如果还不行用errorsreplace强行读入再手动清洗乱码字符。5.2 列名带空格或特殊字符后续引用报 KeyError现象df[销售额]报 KeyError但打印列名明明有。原因列名前后有空格或不可见字符。解决读入后立刻统一清洗列名df.columns df.columns.str.strip().str.replace( , _).str.replace(r[^\w], , regexTrue)这行把空格换下划线去掉非字母数字下划线字符。清洗后再引用就不会出玄学问题。5.3 数值列被读成 objectdescribe 只给计数现象df.info()显示某列 dtype 是 object但肉眼看去全是数字。原因列里混了“未知”“-”或千分位逗号。解决先替换脏字符再转类型df[销售额] df[销售额].replace({未知: np.nan, -: np.nan, ,: }, regexTrue).astype(float)regexTrue让逗号替换生效。转完后用df[销售额].isnull().sum()确认缺失数量再决定填充策略。5.4 KMeans 跑出来所有样本一个簇现象聚类结果只有一个标签轮廓系数报错。原因特征没标准化或者某个特征方差极大主导了距离。解决确认StandardScaler已应用并检查是否有常量列方差为 0导致距离计算失效。用df[feature_cols].nunique()看每列唯一值数量等于 1 的列直接删掉。5.5 交叉验证分数远低于单次划分现象train_test_split的 f1 有 0.9交叉验证只有 0.6。原因单次划分恰好把容易的样本分到了测试集或者数据有顺序比如按时间排列导致折间分布差异大。解决分类任务用StratifiedKFold时间序列用TimeSeriesSplit并且打乱数据前先确认没有泄漏比如用未来信息预测过去。如果折间方差大考虑增加数据量或减少特征。6. 把实训数据变成可复用的分析模板走到这里你已经能把一个实训数据.zip从解压读到建模评估。但下次换个压缩包难道还要重写一遍我的习惯是抽一个最小模板函数把读取、清洗、类型转换、缺失处理串起来参数化文件路径和编码def load_and_clean(path, encodingutf-8, target_colNone): df pd.read_csv(path, encodingencoding) df.columns df.columns.str.strip().str.replace( , _) df df.drop_duplicates() # 数值列脏字符清洗 for col in df.select_dtypes(includeobject).columns: df[col] df[col].replace({未知: np.nan, -: np.nan}) # 缺失填充 for col in df.columns: if df[col].dtype object: df[col] df[col].fillna(df[col].mode()[0] if not df[col].mode().empty else 未知) else: df[col] df[col].fillna(df[col].median()) return df这个函数不完美但能覆盖 80% 的实训数据场景。参数target_col暂时没用上你可以扩展成自动分离特征和标签。验证方法很简单拿同一批数据跑两次确认输出形状和缺失数一致。如果结果不稳定检查mode()是否返回多个值导致填充不一致。另一个实用技巧是给每个数据集存一份profile报告用df.describe(includeall).to_csv(profile.csv)落盘下次直接看文件不用重新跑代码。我一般还会把清洗后的数据存成 parquet 格式读取速度比 CSV 快好几倍df.to_parquet(shixun_data/cleaned.parquet, indexFalse) # 下次直接 pd.read_parquet(shixun_data/cleaned.parquet)parquet 保留 dtype不会出现读回来又变 object 的后悔药场景。唯一注意的是 parquet 对中文列名支持没问题但某些旧版 pandas 需要装pyarrowpip install pyarrow即可。最后说个我自己的教训早期做实训时我总想一步到位把模型调到最优结果在特征工程上偷懒用原始列硬跑最后 f1 卡在 0.5 上不去。后来强迫自己先花 70% 时间做数据理解和清洗模型只用默认参数反而轻松到 0.8。数据挖掘这行脏数据才是最大的黑匣子你把它拆明白了后面都是顺水推舟。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
细胞图像分割实战:UNet与UNet++选型及Python实现 简介:这份资源面向计算机相关专业正在做毕业设计、课程设计或期末大作业的学生,以及需要医学图像分割实战练习的学习者,提供基于UNet与UNet两种经典网络对细胞图像进行分割的完整Python实现。压缩包共48个文件,以44个py源码为主&a… · 2026/9/23 13:46:32
Prisma API 详解:基于数据模型自动生成的 GraphQL 接口与 Playground 探索指南 后端数据库GraphQL 【免费下载链接】prisma1 💾 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL & MongoDB) [deprecated] 项目地址: https://gitcode.com/gh_mirrors/pr/prisma1 点击查看 免费下载 本篇指南聚焦 Prisma&… · 2026/9/23 14:30:48
Nginx UI 集成 Casdoor:OAuth 2.0 统一身份认证接入指南 Nginx UI 集成 Casdoor:OAuth 2.0 统一身份认证接入指南 【免费下载链接】nginx-ui Yet another WebUI for Nginx 项目地址: https://gitcode.com/gh_mirrors/ngi/nginx-ui
本篇技术指南围绕 Nginx UI 的 Casdoor 认证提供方配置展开,完整讲解 En… · 2026/9/23 14:30:47
风冷发动机散热仿真优化实战与Ansys应用 1. 项目概述:风冷发动机散热仿真实战作为一名长期从事热仿真分析的工程师,我最近完成了一个很有意思的风冷摩托车发动机散热优化项目。这类发动机依靠空气流动带走热量,金属散热片的设计直接决定了散热效率。通过Ansys Workbench平台… · 2026/9/23 14:30:25
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29