简介:这份实训数据包面向正在学习Python数据分析与挖掘的在校学生与转行自学者,围绕真实业务场景提供可动手练习的数据素材,帮助读者把数据清洗、探索性分析、特征工程与机器学习建模等环节串联成完整实践链路。包内共17个文件,以csv数据表为主,辅以xlsx、xls表格和sql建表脚本,压缩包约112.9MB,覆盖用户信息、消费记录、商品销售、内容浏览日志等典型数据集,可直接用于Pandas读取、可视化绘图与Scikit-Learn建模练习。目前已有395人学习下载。数据按章节组织,涉及缺失值与异常值处理、描述性统计与图表呈现、多源数据导入导出、特征选择与编码、线性回归与决策树等监督学习算法,以及神经网络入门内容,便于读者按学习进度逐章复现案例,在真实数据上巩固从预处理到模型评估的完整流程。
1. 从一份实训数据包说起:Python 数据分析与挖掘到底练什么
很多人学 Python 数据分析,卡在第一步不是不会写代码,而是手里没有一份像样的数据。网上找的 CSV 要么字段太少,要么全是英文看不懂,要么干脆就是随机生成的假数据,跑完df.head()就不知道该干嘛了。这份「Python数据分析与挖掘实战_实训数据.zip」解决的就是这个问题——它把一门完整课程里用到的实训数据按章节打包好了,从第 2 章的学生基本信息,到第 10 章的日志表字段说明,覆盖了数据清洗、探索性分析、特征工程、用户行为分析、销售预测等典型场景。适合正在跟着教材或视频课做练习的人,也适合想找一套结构完整的数据集来练手 Pandas、Matplotlib、Scikit-Learn 的从业者。下面我按实际拆包后的使用路径,把每章数据怎么用、参数怎么设、哪里容易翻车讲清楚。
2. 拆包先看目录:各章节数据文件的定位与加载方式
2.1 文件清单与对应技术点
拿到压缩包先别急着解压到桌面,我一般会先建一个项目目录,把数据按章节分好。这份资源里的文件大致可以分成四类:基础信息类(学生基本信息.xls、USER_INFO.csv、USER_INFO_M.csv)、交易流水类(acc_records.csv、data.csv、user_balance_table.csv)、商品与销售类(各化妆品销量.xlsx、新零售智能销售设备6月份商品销售情况.xlsx、Supermarket-customers.csv)、日志与行为类(jc_content_viewlog1.sql、jc_content_viewlog1表的字段说明.xlsx、user_info_screen.csv、communication.csv)。第 7 章的 drink.csv、Breakfast.csv、bread.csv 属于典型的关联规则挖掘数据集,第 5 章的 testset.csv 则是留给模型验证用的。
| 章节 | 代表文件 | 格式 | 典型用途 |
|---|---|---|---|
| 第2章 | 学生基本信息.xls | Excel | 基础统计、分组聚合 |
| 第3章 | 各化妆品销量.xlsx | Excel | 可视化、趋势分析 |
| 第4章 | USER_INFO.csv | CSV | 数据清洗、缺失值处理 |
| 第5章 | acc_records.csv、testset.csv | CSV | 分类模型训练与验证 |
| 第6章 | USER_INFO_M.csv | CSV | 用户画像、特征工程 |
| 第7章 | drink.csv、Breakfast.csv、bread.csv | CSV | 关联规则、频繁项集 |
| 第8章 | user_balance_table.csv | CSV | 时间序列、余额预测 |
| 第9章 | user_info_screen.csv | CSV | 筛选、条件过滤 |
| 第10章 | jc_content_viewlog1.sql | SQL | 日志分析、SQL 导入 |
加载时有个细节:.xls是老版 Excel 格式,Pandas 读它需要xlrd库,而.xlsx需要openpyxl。很多人装完 Pandas 直接read_excel报错,就是缺了这两个引擎之一。我一般会在项目开始前统一装好:
pip install pandas numpy matplotlib seaborn scikit-learn xlrd openpyxl sqlalchemy pymysql这条命令里xlrd负责.xls,openpyxl负责.xlsx,sqlalchemy和pymysql是为第 10 章的 SQL 文件准备的。如果你用的是 Anaconda,大部分库已经自带,但xlrd新版本不再支持.xls以外的格式,所以读.xlsx必须靠openpyxl,这一点后面避坑章节还会展开。
2.2 统一加载脚本与编码处理
CSV 文件最烦人的就是编码。这份资源里的 CSV 有些是 UTF-8,有些可能是 GBK 或 GB2312,直接pd.read_csv会抛UnicodeDecodeError。我的习惯是写一个带异常回退的加载函数,先试 UTF-8,失败再试 GBK,再失败试 GB18030。这样不管文件来自 Windows 还是 Linux 环境,都能读进来。
import pandas as pd def load_csv_smart(filepath, **kwargs): """按 UTF-8 -> GBK -> GB18030 顺序尝试读取 CSV""" encodings = ['utf-8', 'gbk', 'gb18030'] for enc in encodings: try: df = pd.read_csv(filepath, encoding=enc, **kwargs) print(f"[OK] {filepath} 使用编码 {enc},形状 {df.shape}") return df except UnicodeDecodeError: continue raise ValueError(f"无法读取 {filepath},请检查文件编码") # 示例:读取第4章用户信息 user_info = load_csv_smart('第4章/USER_INFO.csv') print(user_info.dtypes) print(user_info.isnull().sum())这段代码的关键在encodings列表的顺序和try/except的捕获类型。UnicodeDecodeError是编码不匹配时 Pandas 抛出的典型异常,捕获它继续试下一个编码即可。**kwargs让你可以继续传sep、header、usecols等参数,不影响原有灵活性。打印dtypes和isnull().sum()是为了在加载后立刻确认字段类型和缺失情况,避免后面分析时才发现某列全是字符串。
对于 Excel 文件,加载方式类似,但要注意sheet_name参数。一个.xlsx里可能有多个工作表,不指定就只读第一个。第 3 章的「各化妆品销量.xlsx」和「新零售智能销售设备6月份商品销售情况.xlsx」很可能有多个 sheet,我一般先用pd.ExcelFile看一眼再决定读哪个:
xl = pd.ExcelFile('第3章/各化妆品销量.xlsx', engine='openpyxl') print(xl.sheet_names) # 先看有哪些工作表 df_sales = xl.parse(xl.sheet_names[0]) # 再按需读取engine='openpyxl'是显式指定引擎,避免 Pandas 自动推断时选错。如果你环境里同时装了xlrd和openpyxl,不指定引擎有时会报版本冲突,这个坑后面会细说。
3. 数据清洗与探索:从 USER_INFO 到可视化落地
3.1 缺失值与异常值处理的标准流程
第 4 章的USER_INFO.csv和第 6 章的USER_INFO_M.csv是练数据清洗的好材料。真实业务数据里,用户信息表通常会有缺失的手机号、空白的年龄、格式不统一的日期。我一般按「先看分布,再定策略」的顺序走:数值列看describe(),类别列看value_counts(),日期列看pd.to_datetime的报错情况。
# 数值列分布 print(user_info.describe()) # 类别列取值分布 for col in user_info.select_dtypes(include='object').columns: print(f"\n{col} 取值前10:") print(user_info[col].value_counts().head(10)) # 缺失值比例 missing_ratio = user_info.isnull().sum() / len(user_info) print(missing_ratio[missing_ratio > 0].sort_values(ascending=False))这段代码的输出决定了你后面怎么填。缺失比例低于 5% 的数值列,我通常用中位数填充;高于 30% 的列,考虑直接丢弃或作为单独类别标记。类别列缺失可以填'Unknown',但要注意这会影响后续分组聚合的结果。describe()还能帮你发现异常值,比如年龄出现 200 或 -1,这种明显超出业务范围的数值,要么截断要么置空。
异常值检测常用 IQR 方法,不依赖正态分布假设,比 3σ 更稳健:
def detect_outliers_iqr(df, col): Q1 = df[col].quantile(0.25) Q3 = df[col].quantile(0.75) IQR = Q3 - Q1 lower = Q1 - 1.5 * IQR upper = Q3 + 1.5 * IQR outliers = df[(df[col] < lower) | (df[col] > upper)] print(f"{col}: 下界 {lower:.2f}, 上界 {upper:.2f}, 异常数 {len(outliers)}") return outliers # 对年龄列做异常检测 outliers_age = detect_outliers_iqr(user_info, 'age')1.5 * IQR是经典阈值,业务上如果数据本身波动大,可以放宽到 3 倍 IQR。返回的outliers不要直接删,先看看这些行是不是有特殊含义,比如高消费用户被当成异常删掉就亏大了。
3.2 用 Matplotlib 和 Seaborn 做探索性可视化
第 3 章的化妆品销量数据适合练可视化。我一般会先画一个按品类分组的柱状图看整体分布,再用箱线图看各品类的离散程度,最后用热力图看字段间的相关性。Seaborn 的boxplot和heatmap比 Matplotlib 原生接口省事很多。
import matplotlib.pyplot as plt import seaborn as sns plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文显示 plt.rcParams['axes.unicode_minus'] = False # 假设 df_sales 有 '品类' 和 '销量' 两列 fig, axes = plt.subplots(1, 2, figsize=(14, 5)) sns.barplot(data=df_sales, x='品类', y='销量', ax=axes[0]) axes[0].set_title('各品类销量对比') axes[0].tick_params(axis='x', rotation=45) sns.boxplot(data=df_sales, x='品类', y='销量', ax=axes[1]) axes[1].set_title('各品类销量分布') plt.tight_layout() plt.savefig('sales_overview.png', dpi=150) plt.show()SimHei是 Windows 自带中文字体,Linux 或 Mac 上可能没有,需要换成WenQuanYi Micro Hei或Arial Unicode MS。不设这个参数,中文标签会变成方块。dpi=150是保存图片的分辨率,写报告够用,再高文件会很大。tight_layout()自动调整子图间距,避免标签被截断。
热力图之前要先做相关性计算,只保留数值列:
numeric_df = df_sales.select_dtypes(include=['float64', 'int64']) corr = numeric_df.corr() plt.figure(figsize=(10, 8)) sns.heatmap(corr, annot=True, fmt='.2f', cmap='coolwarm', center=0) plt.title('数值字段相关性热力图') plt.show()annot=True把相关系数写在格子里,fmt='.2f'保留两位小数,center=0让颜色以 0 为中心对称,正相关偏红、负相关偏蓝。相关系数绝对值大于 0.7 的字段对,后面建模时要注意多重共线性,可以考虑删掉其中一个。
4. 关联规则与用户行为:第 7 章和第 10 章的实战路径
4.1 从 drink.csv 到频繁项集:Apriori 参数怎么调
第 7 章的drink.csv、Breakfast.csv、bread.csv是典型的购物篮数据,适合练关联规则挖掘。这类数据通常长成「订单号 + 商品名」的格式,一行一个商品,同一个订单号有多行。用 Apriori 之前要先做透视,把数据转成「一行一个订单、每列一个商品」的 0-1 矩阵。
# 假设 drink.csv 有 '订单号' 和 '商品' 两列 drink = pd.read_csv('第7章/drink.csv', encoding='gbk') # 透视成 0-1 矩阵 basket = drink.groupby(['订单号', '商品'])['商品'].count().unstack().fillna(0) basket = basket.applymap(lambda x: 1 if x > 0 else 0) print(basket.shape) print(basket.head())groupby加unstack是购物篮数据透视的标准操作,fillna(0)把没有购买记录的位置填 0,applymap把计数转成 0-1。数据量大时applymap会慢,可以改用(basket > 0).astype(int),向量化操作快很多。
接下来跑 Apriori,核心参数是min_support(最小支持度)、min_confidence(最小置信度)、min_lift(最小提升度)。支持度太低会产出大量无意义规则,太高又可能一条规则都跑不出来。我的经验是先从 0.01 到 0.05 之间试,看规则数量再调整。
from mlxtend.frequent_patterns import apriori, association_rules frequent_itemsets = apriori(basket, min_support=0.02, use_colnames=True) print(f"频繁项集数量:{len(frequent_itemsets)}") rules = association_rules(frequent_itemsets, metric='confidence', min_threshold=0.3) rules = rules[rules['lift'] > 1.0].sort_values('lift', ascending=False) print(rules[['antecedents', 'consequents', 'support', 'confidence', 'lift']].head(10))min_support=0.02表示一个商品组合至少在 2% 的订单里同时出现。metric='confidence'配合min_threshold=0.3表示只看置信度大于 30% 的规则。lift > 1.0是筛选有效关联的底线,提升度小于等于 1 说明两个商品之间没有正向关联,甚至可能是负相关。mlxtend不是 Pandas 自带库,需要单独pip install mlxtend。
4.2 第 10 章 SQL 日志表的导入与字段解析
第 10 章给了jc_content_viewlog1.sql和对应的字段说明 Excel,这是练 SQL 导入和日志分析的素材。.sql文件不能直接用 Pandas 读,常见做法是先导入 MySQL 或 SQLite,再用pd.read_sql查出来。如果只是本地练习,SQLite 最省事,不需要装数据库服务。
# 用 sqlite3 导入 SQL 文件 sqlite3 viewlog.db < 第10章/jc_content_viewlog1.sql导入后先用字段说明 Excel 对照一下表结构,确认字段名和类型:
import sqlite3 conn = sqlite3.connect('viewlog.db') field_desc = pd.read_excel('第10章/jc_content_viewlog1表的字段说明.xlsx', engine='openpyxl') print(field_desc) # 查前 5 行 sample = pd.read_sql('SELECT * FROM jc_content_viewlog1 LIMIT 5', conn) print(sample)sqlite3是 Python 内置库,不需要额外安装。pd.read_sql直接接收 SQL 语句和连接对象,返回 DataFrame。字段说明 Excel 里通常有字段名、类型、含义三列,先看一遍再写查询,能避免把content_id当成user_id这种低级错误。日志表数据量大时,不要SELECT *全量拉,加LIMIT或WHERE条件分批取。
5. 避坑与排查:这份实训数据最容易翻车的五个地方
5.1 读 Excel 报错 xlrd 版本不兼容
现象:pd.read_excel('学生基本信息.xls')抛出XLRDError: Excel xlsx file; not supported。原因:新版xlrd只支持.xls,不支持.xlsx,而 Pandas 默认可能仍调用xlrd。解决:读.xlsx时显式指定engine='openpyxl',读.xls时用engine='xlrd',两个库都装上,各管各的。
5.2 CSV 中文乱码导致列名变成乱码
现象:df.columns输出一堆\xca\xfd\xbe\xdd之类的字符。原因:文件是 GBK 编码,但用 UTF-8 读了。解决:用前面load_csv_smart函数自动回退编码,或者手动指定encoding='gbk'。如果列名已经乱了,重新读一遍即可,不要试图在乱码基础上改列名。
5.3 关联规则跑不出结果或规则爆炸
现象:apriori返回空 DataFrame,或者返回几万条规则。原因:min_support设得太高或太低。解决:先算一下商品出现频率,把min_support设在「出现次数最多的商品频率」的 1/10 到 1/5 之间。规则太多就提高min_confidence和lift阈值,规则为空就降低min_support。
5.4 SQL 文件导入后表名为空或字段缺失
现象:sqlite3导入成功但SELECT报no such table。原因:.sql文件里可能包含CREATE DATABASE或USE语句,SQLite 不支持。解决:先用文本编辑器打开.sql文件,删掉CREATE DATABASE、USE等非标准语句,只保留CREATE TABLE和INSERT INTO,再导入。
5.5 可视化中文显示为方块
现象:图表标题和轴标签全是□□□。原因:Matplotlib 默认字体不含中文。解决:设置plt.rcParams['font.sans-serif'] = ['SimHei'],Mac 上换成['Arial Unicode MS'],Linux 上换成['WenQuanYi Micro Hei']。设置后如果还不生效,清一下 Matplotlib 缓存:rm -rf ~/.matplotlib。
6. 进阶技巧:用 testset.csv 做一次完整的模型验证闭环
第 5 章的acc_records.csv和testset.csv可以串成一个完整的分类模型验证流程。acc_records.csv当训练集,testset.csv当测试集,中间走一遍特征工程、模型训练、混淆矩阵评估。我一般会先确认两个文件的字段是否一致,不一致就以训练集为准做列对齐。
from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix from sklearn.preprocessing import LabelEncoder # 加载 train = load_csv_smart('第5章/acc_records.csv') test = load_csv_smart('第5章/testset.csv') # 假设目标列叫 'label',其余为特征 target = 'label' feature_cols = [c for c in train.columns if c != target] # 类别编码 le = LabelEncoder() for col in train[feature_cols].select_dtypes(include='object').columns: train[col] = le.fit_transform(train[col].astype(str)) test[col] = le.transform(test[col].astype(str)) # 训练 X_train = train[feature_cols] y_train = train[target] X_test = test[feature_cols] y_test = test[target] clf = RandomForestClassifier(n_estimators=100, random_state=42) clf.fit(X_train, y_train) # 评估 y_pred = clf.predict(X_test) print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred))LabelEncoder对每一列单独编码,训练集和测试集必须用同一个编码器,否则类别映射会错位。random_state=42保证结果可复现。classification_report输出精确率、召回率、F1 值,比只看准确率更能发现类别不平衡问题。如果测试集里出现了训练集没有的类别,le.transform会报错,这时候要么把新类别归为'Unknown',要么用handle_unknown='ignore'的OrdinalEncoder替代。
跑完这一遍,你会对「数据加载 → 清洗 → 特征编码 → 模型训练 → 评估」的完整链路有个具体感受。这份实训数据的价值不在于文件本身多稀有,而在于它把每个环节需要的素材都准备好了,省去了到处找数据的麻烦。从那以后我每次拿到新数据集,都会先跑一遍load_csv_smart加describe()加isnull().sum()这三板斧,确认数据底子干净了再往下走。希望帮到你。
本文还有配套的精品资源,点击获取