模块三-数据清洗与预处理——12. 缺失值处理(上):检测与删除
12. 缺失值处理上检测与删除1. 概述现实世界的数据很少是完美的缺失值是最常见的数据质量问题之一。缺失值可能来自数据录入错误、传感器故障、数据合并不匹配等原因。正确处理缺失值是数据清洗的第一步。importpandasaspdimportnumpyasnp# 创建包含缺失值的示例数据np.random.seed(42)dfpd.DataFrame({姓名:[张三,李四,王五,赵六,钱七,孙八],年龄:[25,np.nan,28,32,np.nan,27],工资:[8000,12000,np.nan,15000,11000,9500],部门:[技术,销售,技术,np.nan,销售,技术],绩效:[A,B,np.nan,A,C,B]})print(原始数据:)print(df)2. 缺失值的表示2.1 Pandas 中的缺失值Pandas 使用以下几种方式表示缺失值类型表示说明NonePython 原生对象类型列的缺失值np.nanNumPy浮点数/整数列的缺失值推荐pd.NAPandasPandas 1.0 新增统一缺失值表示# 不同列类型的缺失值表示print(数据类型:)print(df.dtypes)print(\n缺失值表示:)print(df.iloc[1,1])# 年龄列float64→ nanprint(df.iloc[3,3])# 部门列object→ nan2.2 缺失值的特点# nan 与任何值比较都为 Falseprint(fnp.nan np.nan:{np.nannp.nan})# Falseprint(fnp.nan is np.nan:{np.nanisnp.nan})# True# 使用 pd.isna() 检测print(fpd.isna(np.nan):{pd.isna(np.nan)})# True3. 检测缺失值3.1 isna() / isnull()isna()和isnull()功能相同返回布尔值的 DataFrameTrue 表示缺失。# 检测缺失值print(缺失值检测:)print(df.isna())# 每列缺失值数量print(\n每列缺失值数量:)print(df.isna().sum())# 每行缺失值数量print(\n每行缺失值数量:)print(df.isna().sum(axis1))# 缺失值比例print(\n每列缺失值比例:)print(df.isna().sum()/len(df)*100)3.2 notna() / notnull()notna()和notnull()与isna()相反返回非缺失值的位置。# 非缺失值检测print(非缺失值检测:)print(df.notna())# 每列非缺失值数量print(\n每列非缺失值数量:)print(df.notna().sum())3.3 综合统计# 创建缺失值统计报告missing_reportpd.DataFrame({列名:df.columns,数据类型:df.dtypes.values,缺失值数量:df.isna().sum().values,缺失值比例(%):(df.isna().sum()/len(df)*100).values,非缺失值数量:df.notna().sum().values})print(缺失值统计报告:)print(missing_report)4. 删除缺失值4.1 dropna() 基础用法dropna()删除包含缺失值的行或列。# 删除任何包含缺失值的行print(删除包含缺失值的行:)df_dropped_rowsdf.dropna()print(df_dropped_rows)print(f原数据行数:{len(df)}, 删除后行数:{len(df_dropped_rows)})# 删除任何包含缺失值的列print(\n删除包含缺失值的列:)df_dropped_colsdf.dropna(axis1)print(df_dropped_cols)4.2 控制删除条件# howall只删除全部为缺失值的行print(删除全为缺失值的行:)df_all_napd.DataFrame({A:[1,np.nan,3],B:[2,np.nan,4],C:[3,np.nan,5]})print(df_all_na.dropna(howall))# thresh至少保留 n 个非缺失值print(\n至少保留2个非缺失值:)print(df.dropna(thresh2))# subset指定检查的列print(\n只在年龄和工资列检查缺失:)print(df.dropna(subset[年龄,工资]))4.3 原地删除# inplaceTrue 原地修改df_copydf.copy()df_copy.dropna(inplaceTrue)print(原地删除后:)print(df_copy)5. 处理特定列的缺失值5.1 筛选非缺失行# 保留年龄非缺失的行print(年龄非缺失:)print(df[df[年龄].notna()])# 保留工资非缺失的行print(\n工资非缺失:)print(df[df[工资].notna()])# 多个条件print(\n年龄和工资都非缺失:)print(df[df[年龄].notna()df[工资].notna()])5.2 删除缺失值过多的列# 删除缺失率超过50%的列missing_ratedf.isna().sum()/len(df)cols_to_dropmissing_rate[missing_rate0.5].index.tolist()print(f缺失率50%的列:{cols_to_drop})ifcols_to_drop:df_cleaneddf.drop(columnscols_to_drop)print(删除后:)print(df_cleaned)else:print(没有缺失率超过50%的列)6. 缺失值可视化importmatplotlib.pyplotaspltimportseabornassns# 缺失值矩阵可视化plt.figure(figsize(10,4))sns.heatmap(df.isna(),cbarFalse,cmapviridis,yticklabelsFalse)plt.title(缺失值分布图黄色缺失)plt.show()# 缺失值比例条形图missing_percentdf.isna().sum()/len(df)*100missing_percentmissing_percent[missing_percent0].sort_values(ascendingFalse)iflen(missing_percent)0:plt.figure(figsize(8,4))missing_percent.plot(kindbar)plt.title(各列缺失值比例)plt.ylabel(缺失比例 (%))plt.xlabel(列名)plt.xticks(rotation45)plt.tight_layout()plt.show()7. 完整示例销售数据清洗# 创建包含缺失值的销售数据np.random.seed(42)salespd.DataFrame({订单号:[fORD{i:04d}foriinrange(1,21)],产品:np.random.choice([A,B,C,D],20),销售额:np.random.randint(100,1000,20).astype(float),数量:np.random.randint(1,20,20),客户:[f客户_{i}foriinrange(1,21)],地区:np.random.choice([华东,华南,华北,西南],20)})# 随机添加缺失值forcolin[销售额,数量,客户,地区]:idxnp.random.choice(20,3,replaceFalse)sales.loc[idx,col]np.nanprint(*60)print(销售数据清洗)print(*60)print(\n原始数据:)print(sales.head(10))# 1. 检查缺失情况print(\n1. 缺失值统计:)missing_statssales.isna().sum()print(missing_stats[missing_stats0])# 2. 删除关键字段缺失的记录print(\n2. 删除订单号、销售额缺失的记录:)sales_cleanedsales.dropna(subset[订单号,销售额])print(f删除前:{len(sales)}行, 删除后:{len(sales_cleaned)}行)# 3. 删除缺失过多的列print(\n3. 检查列缺失率:)col_missing_ratesales.isna().sum()/len(sales)print(col_missing_rate.round(3))# 4. 最终数据print(\n4. 清洗后数据:)print(sales_cleaned.head())8. 注意事项注意事项说明删除 vs 填充删除会丢失信息填充更常用随机缺失 vs 系统性缺失随机缺失可删除系统性缺失需分析原因小样本数据删除可能损失过多信息时间序列不能随意删除需考虑时间连续性9. 总结方法用途示例isna()/isnull()检测缺失值df.isna().sum()notna()/notnull()检测非缺失值df[df[col].notna()]dropna()删除缺失值df.dropna()dropna(howall)删除全缺失行df.dropna(howall)dropna(threshn)保留至少n个非缺失df.dropna(thresh3)dropna(subset[...])指定检查列df.dropna(subset[col1,col2])dropna(axis1)删除包含缺失的列df.dropna(axis1)