
简介数据预处理是数据挖掘过程中的重要环节。这份课后答案文档面向数据分析初学者系统讲解了重复值检查、缺失值处理、异常值检测与处理、数据集成、数据变换、数据规范化以及连续属性离散化等核心知识点。资源共包含1个Word格式文档压缩包大小仅10KB轻量便携便于直接打开阅读和打印。文档结合流程图与具体代码示例先介绍重复值的识别与删除、缺失值的删除法替换法插补法再说明基于箱线图的异常值判定与四种处理方式后续覆盖最小最大规范化、零均值规范化、小数定标规范化以及等宽法等频法聚类等离散化手段并补充了变量属性构造与小波变换等拓展内容。每题后均附有通俗解释和参考代码能够帮助读者快速掌握数据清洗与特征变换的实用技巧。目前已有262人学习下载适合正在学习数据预处理或准备数据挖掘项目的人员使用。1. 把“python数据预处理课后答案.docx”当作动手清单身边不时有人拿着《python数据预处理课后答案.docx》来问框起一份 Word 文件里面往往不是一份可以直接复制的最终答案而是一串题目要求和目标输出。数据预处理本来就是数据分析里最“脏”也最容易被扣分的一段缺失值怎么补、重复值怎么删、类别特征怎么编码、数值该标准化还是归一化。我通常把这类作业拆成四步处理数据清洗、数据转换、数据重构、提交前验证。这四步基本能覆盖 pandas 和 scikit-learn 在数据预处理阶段的大部分考点也适合刚学 Python 数据分析的同学一次性跑通“读数据、改类型、补缺失、降维度”。哪怕题版里出现“头歌”或“第1关数据预处理之数据转换”这些字样下面这套流程也能直接对应过去。2. 拆解数据预处理作业的考点地图与库选型2.1 四类高频考题清洗、转换、重构、验证数据预处理不是一段固定代码而是围绕“让表格更好进模型”的一组动作。课程作业经常会按关卡拆题目第一关做数据清洗包括缺失值、重复值、类型错乱第二关做数据转换包括文本编码、数值缩放第三关做数据重构涉及表的拼接、分组聚合最后一关是导出一份“干净结果表”用来和老师给出的目标文件对比。这个顺序不能乱清洗没做完就做编码会把脏数据也一起编码进去。我一般不会按题面顺序从上到下写答案而是先建立一个带顺序的 pipeline清洗在转换之前转换在重构之前验证放在最后。这样每道小题的输出都只依赖前一步的结果出错时容易定位是哪一个环节。比如缺失值用中位数填充后再做标准化平均值才不会先被异常值带偏如果前置步骤把字符串变成了 NaN后续fillna才能真正接手。2.2 pandas、numpy、scikit-learn 怎么分工很多同学拿到题就写df.dropna()并不是因为数据需要这样做而是因为“只会这一句”。要避免这种误用先把工具边界分清楚。下表是我在题里常用的分工方式按“负责面”来选 API。库主要负责常用入口对应考点pandas表格读写、筛选、缺失值、重复值、合并pd.read_csv、df.fillna、df.drop_duplicates数据清洗、数据转换numpy数组运算和数值计算np.where、np.isnan、np.abs异常值判断、条件构造scikit-learn编码、缩放、降维StandardScaler、OneHotEncoder、PCA特征转换、数据降维matplotlib/seaborn分布与异常值可视化plt.hist、sns.boxplot验证结果分布这里面最容易混的是 pandas 和 scikit-learn。pandas 偏向“表格形态的整理”比如删行、拆列、改名scikit-learn 偏向“数学转换”比如标准化、主成分分析。作业最后如果要求输出一张新表通常先用 pandas 整理再在进入模型前用 sklearn。2.3 打开空白脚本后的第一段固定代码不管题目文件叫什么我的开头永远是一段环境检查和数据基础探查。这段代码能把 Python、pandas、numpy 的版本和原始数据形态一起打出来避免后面出现“本地能跑、交了不行”的版本差异。import sys import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler, MinMaxScaler from sklearn.decomposition import PCA print(python, sys.version.split()[0]) print(pandas, pd.__version__) print(numpy, np.__version__) df pd.read_csv(raw_data.csv) print(df.shape) print(df.info()) print(df.isnull().mean())这段代码做了三件事shape先确认行数和列数方便后面比对去重或合并造成的数量变化info()输出每列的非空计数和 dtype一眼看出哪些列需要做类型转换isnull().mean()给出每列缺失比例作为填充策略的判断依据。如果运行后提示缺少库直接在终端执行pip install pandas numpy scikit-learn并把安装版本逐行记录在答案说明里。3. 用 pandas 完成清洗与异常值处理先守住数据质量3.1 缺失值不是删掉就完先看比例再决定填充策略缺失值处理最忌讳df.dropna()一把梭。在作业题里考官通常会给某一列预留 20% 到 30% 的缺失直接删行会导致样本量缩水最后输出和参照表对不上号。正确顺序是先统计缺失比例再看这一列是数值型还是分类型最后决定填充方式。# 统计缺失率并只打印存在缺失的列 miss_rate df.isnull().mean().round(4) print(miss_rate[miss_rate 0]) # 数值列用中位数填充保留分布中心 num_cols [age, income] for col in num_cols: if df[col].isnull().any(): df[col] df[col].fillna(df[col].median()) # 分类列用统一标记填充留下“缺失过”的线索 cat_cols [city, job] for col in cat_cols: df[col] df[col].fillna(unknown)逻辑说明isnull().mean()返回每列缺失比例round(4)只是让输出更容易阅读。中位数比均值更抗极端值所以年龄、收入这类偏态列一般不用平均数填充。分类列填“unknown”而不是直接删除是为了保留“该样本在某个字段上信息不全”这个事实如果填众数反而会让缺失样本伪装成正常样本。如果数据是时间序列比如每天的销售额漏了一天fillna就不够合适常见做法是先ffill()再用bfill()补齐首尾。这类“差分逻辑”在作业里容易作为加分项出现。3.2 重复值的判定范围行级、部分列级与合并后重复去重题并不总是把整行重复删掉那么简单。数据表可能只有 ID 列重复其余字段不同这种叫“部分列重复”需要用subset指定判断依据。还有一种是两个表合并后主键重复那不是原始脏数据而是合并方式写错导致的需要单独查。# 整行重复直接去重 before df.shape[0] df df.drop_duplicates() print(删除整行重复, before - df.shape[0]) # 按 order_id 去重同一订单只保留最后一条状态 df df.drop_duplicates(subset[order_id], keeplast) # 合并后检查主键是否被放大 counts df.groupby([user_id, date]).size() print(counts[counts 1])参数说明subset指定判断重复的列名列表keeplast表示保留重复组内最后一行适合日志表保留最新状态默认值是first也就是保留第一行。groupby(...).size()返回组合键出现次数大于 1 的地方就是重复来源。很多作业只要求“把重复行去掉”但阅卷时会看你是否能说清楚为什么保留这一行而不是另一行。3.3 异常值用 IQR 和 3σ 两种口径标记异常值题很少要求直接删除更多是“把超过阈值的数据标记出来”。IQR 和 3σ 是两种最常用的口径两者对同一个数据集的判定结果可能不同所以我一般把两个 mark 都做出来方便对照题目要求。def flag_outliers_iqr(s: pd.Series) - pd.Series: q1 s.quantile(0.25) q3 s.quantile(0.75) iqr q3 - q1 lower q1 - 1.5 * iqr upper q3 1.5 * iqr return (s lower) | (s upper) df[is_outlier_iqr] flag_outliers_iqr(df[income]) mean df[income].mean() std df[income].std() df[is_outlier_3sigma] (df[income] - mean).abs() 3 * std函数说明Series.quantile(0.25)求下四分位数IQR 是上下四分位之差边界取在Q1 - 1.5*IQR和Q3 1.5*IQR。两个边界之外标记为离群点。3σ 方法用均值加减 3 倍标准差假设数据接近正态分布。两种口径的适用差异如下口径分布假设稳健性适用场景IQR不要求正态分布中位数和四分位不受极端值影响收入、销售额等偏态分布3σ近似正态分布均值、方差会被异常值本身拉偏考试中明确说“按正态假设”注意3σ 看起来严格但如果数据里存在一个特别大的值均值和标准差都会被抬高反而让真正的离群点“躲”进范围内所以标记完一定要配合hist()看一眼分布形状。提示异常值先标记不急着删。作业里如果后续有标准化题保留异常值会比删除更考验缩放策略的合理性。4. 类型转换、编码缩放与重构把答案做完整4.1 先做类型转换再做数值计算数据转换题最容易踩的坑是info()里显示 object但打印出来全是数字。这种“看起来像数字实际是字符串”的列直接df[amount] * 2只会得到字符串拼接结果。标准处理是先把字符串清洗干净再交给pd.to_numeric。# 去掉千分位逗号再用 coerce 强制转数字 df[amount] df[amount].str.replace(,, , regexFalse) df[amount] pd.to_numeric(df[amount], errorscoerce) # 日期列统一格式 df[date] pd.to_datetime(df[date], format%Y-%m-%d)参数说明errorscoerce会把无法解析的内容转为 NaN而不是直接抛异常转完再配合第 3 章的缺失值处理统一解决。str.replace里的regexFalse表示只替换普通字符逗号避免误当成正则表达式。日期列用pd.to_datetime给出format参数除了格式明确速度也比自动解析快很多。做完这步后再执行df.dtypes应该能看到int64、float64、datetime64[ns]这些目标类型。4.2 归一化与标准化不能凭习惯选很多人一看到“数值缩放”就直接套MinMaxScaler其实两道题考的是两个方向一个要求看分布一个要求看取值范围。StandardScaler 输出均值为 0、方差为 1 的分布MinMaxScaler 把数值压到 0 到 1 之间。两者在答案里不能互换。from sklearn.preprocessing import StandardScaler, MinMaxScaler scaler_std StandardScaler() df[income_z] scaler_std.fit_transform(df[[income]]) scaler_mm MinMaxScaler() df[income_minmax] scaler_mm.fit_transform(df[[income]])代码说明sklearn 的fit_transform要求输入是二维结构所以不能写df[income]必须写成df[[income]]。输出分别用_z和_minmax后缀命名是为了后续自检时可以比较两列均值。StandardScaler 处理后mean应该接近 0MinMaxScaler 处理后最小值是 0、最大值是 1。对课后的“数据转换关卡”这两个结果本身就是送分答案。模型或题目要求推荐做法原因线性回归、逻辑回归、SVMStandardScaler让梯度下降更快收敛图像像素值、0-1 得分题MinMaxScaler保留固定区间决策树、随机森林可以不缩放树模型按切分点寻找阈值与尺度无关PCA 降维StandardScaler 先行避免方差被量纲更大的列主导4.3 分类特征编码先看顺序关系分类特征里“低、中、高”和“北京、上海、广州”不是同一种数据。前者有顺序关系用 0、1、2 编码是合理的后者没有顺序一旦按字母排序编码成数字就把“城市”变成了有大小关系的量模型会错误地认为 3 比 2 大。作业里出现顺序型分类的概率很高所以不能只用一种方法处理所有列。# 无序分类用独热编码去掉第一列避免冗余 df pd.get_dummies(df, columns[city], drop_firstTrue) # 顺序分类用自定义映射 level_map {低: 0, 中: 1, 高: 2} df[level_ord] df[level].map(level_map)参数说明get_dummies是 pandas 内置的独热编码函数columns[city]指定被转换的列drop_firstTrue会把“北京”这一类整体去掉避免产生多重共线性。顺序映射用map最直接比sklearn.preprocessing.OrdinalEncoder好在你能随手检查level_map如果题目强制要求用 sklearn也可以改成OrdinalEncoder(categories[[低, 中, 高]])注意 categories 的手写顺序就是将来数值的大小关系。4.4 merge 与 groupby重构类题目的两个高频动作数据重构题不会只给一维表格通常会要求把订单表和用户表合并再按地区、日期做汇总。合并要回答“按哪几个键、取哪种方式”聚合要回答“按哪些列分组、算哪些指标”。这两步写错结果行数很容易和答案对不上。# 左连接订单表全部保留用户信息补充进来 order_user pd.merge( order_df, user_df, onuser_id, howleft, validatemany_to_one ) # 按地区和日期做汇总 summary ( order_user .groupby([region, date], as_indexFalse) .agg({amount: [sum, mean, count]}) ) print(summary.head())代码说明merge里的on指定连接键howleft表示左表每行都保留匹配不到的用户字段补 NaNvalidatemany_to_one会主动检查右表user_id是否唯一防止一对多放大行数。groupby后面跟分组列as_indexFalse让分组列继续留在普通列里而不是变成索引agg里用字典指定列名和聚合函数得到的是带 MultiIndex 列名的 DataFrame提交前可以.round(2)保留两位小数。如果是把两份结构相同的表上下拼接用pd.concat([df1, df2], axis0, ignore_indexTrue)左右拼接则把axis改成 1。这里最容易漏的是ignore_indexTrue不重置索引会让拼接结果出现重复序号后续随机抽样会连带出各种边界问题。5. 提交前用降维验证和 assert 把答案收紧5.1 用 PCA 验证特征是否冗余PCA 在数据预处理作业里多数是选修题但如果题目说“判断特征是否冗余”最好的答案不是写一段描述而是直接给出主成分解释方差。标准化之后再做 PCA看累计方差贡献率达到 0.9 需要几个成分如果十列只压缩成三列就说明原始特征存在明显共线性。X_scaled StandardScaler().fit_transform(df[num_cols]) pca PCA(n_components0.9, random_state42) X_pca pca.fit_transform(X_scaled) print(保留主成分数:, X_pca.shape[1]) print(累计解释方差:, pca.explained_variance_ratio_.sum().round(4))n_components0.9表示保留累计解释方差达到 90% 的成分数random_state固定随机种子保证每次运行结果一致。解释方差总和约等于 0.9说明压缩没有损失太多信息。这里必须先StandardScaler不然量纲大的列会主导 PCA 方向。5.2 用 assert 批量检查结果表提交前我会在脚本末尾放一段 assert把题目最关键的几个条件写进去。检查项包括缺失值清零、重复行清零、分类取值集合、标准化后的均值、目标列数全部通过后才会导出。assert df.isnull().sum().sum() 0, 仍有缺失值 assert df.duplicated().sum() 0, 仍有重复行 assert set(df[city].unique()) {北京, 上海, 广州}, 城市取值异常 assert abs(df[income_z].mean()) 1e-6, 标准化均值偏离0 assert df.shape[1] expected_features, 列数变化异常 df.to_csv(answer_clean.csv, indexFalse, encodingutf-8-sig)assert后面跟条件条件不满足会直接抛异常并打印提示文字。df.shape[1]在这里是最终列数和作业目标表做比对。to_csv的indexFalse是避免多出一列Unnamed: 0encodingutf-8-sig是为了让 Excel 打开中文不出现乱码。最后一句话送一行python preprocess.py head -5 answer_clean.csv这样既能跑通全流程又能快速看到最终输出长什么样。我会把这段固定检查保留在脚本末尾下次换一份数据集只需改掉里面的列名和期望值就能复用。本文还有配套的精品资源点击获取