本文目录导读:

- 准备工作:创建示例数据
- 检查缺失值
- 删除缺失数据(最简单暴力)
- 用固定值填充(最常用)
- 向前/向后填充(时间序列常用)
- 插值法(适合连续数据)
- 用算法预测填充(KNN高级用法)
- 综合案例:不同列用不同策略
- 实际业务案例:销售数据
- 选择策略的建议
在Python中,填充缺失数据通常会用到 Pandas 库,以下是几种最常用的方法,从简单到高级,配有代码案例。
准备工作:创建示例数据
import pandas as pd
import numpy as np
# 创建一个包含缺失值的DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4, 5],
'B': [np.nan, 2, 3, np.nan, 5],
'C': [1, 2, 3, 4, 5],
'D': ['a', np.nan, 'c', 'd', np.nan]
})
print("原始数据:")
print(df)
输出:
A B C D
0 1.0 NaN 1 a
1 2.0 2.0 2 NaN
2 NaN 3.0 3 c
3 4.0 NaN 4 d
4 5.0 5.0 5 NaN
检查缺失值
# 检查哪些是空值 print(df.isnull()) # 统计每列缺失数量 print(df.isnull().sum())
删除缺失数据(最简单暴力)
# 删除包含任何缺失值的行
df_drop_any = df.dropna()
print("删除任何缺失值的行:")
print(df_drop_any)
# 删除全部为缺失值的行
df_drop_all = df.dropna(how='all')
# 删除指定列有缺失的行
df_drop_subset = df.dropna(subset=['A', 'B'])
用固定值填充(最常用)
1 填充常数
# 用0填充所有缺失值
df_fill0 = df.fillna(0)
print("用0填充:")
print(df_fill0)
# 用指定值填充不同列
df_fill_specific = df.fillna({
'A': 999,
'B': 0,
'D': '未知'
})
2 填充统计值
# 用列平均值填充 df_fill_mean = df['A'].fillna(df['A'].mean()) # 用列中位数填充 df_fill_median = df['B'].fillna(df['B'].median()) # 用众数填充(适合分类数据) df_fill_mode = df['D'].fillna(df['D'].mode()[0]) # 应用到整个DataFrame df_numeric = df.select_dtypes(include=[np.number]) df[df_numeric.columns] = df_numeric.fillna(df_numeric.mean())
向前/向后填充(时间序列常用)
# 向前填充(用上一个有效值填充)
df_ffill = df.fillna(method='ffill')
print("向前填充:")
print(df_ffill)
# 向后填充
df_bfill = df.fillna(method='bfill')
# 限制填充次数(比如最多填充2个连续的缺失)
df_ffill_limit = df.fillna(method='ffill', limit=2)
插值法(适合连续数据)
# 线性插值
df_interpolate = df.interpolate()
print("线性插值:")
print(df_interpolate)
# 其他插值方法
df_interp_quadratic = df.interpolate(method='quadratic') # 二次插值
df_interp_spline = df.interpolate(method='spline', order=3) # 样条插值
# 时间序列插值
# df_time.interpolate(method='time')
用算法预测填充(KNN高级用法)
from sklearn.impute import KNNImputer
# 只对数值列进行KNN填充
imputer = KNNImputer(n_neighbors=2)
df_numeric_imputed = pd.DataFrame(
imputer.fit_transform(df_numeric),
columns=df_numeric.columns
)
print("KNN填充:")
print(df_numeric_imputed)
综合案例:不同列用不同策略
def fill_missing_values(df):
"""智能填充缺失值"""
df_filled = df.copy()
for col in df_filled.columns:
if df_filled[col].dtype == 'object': # 字符串列
# 用众数填充
mode_val = df_filled[col].mode()
if not mode_val.empty:
df_filled[col] = df_filled[col].fillna(mode_val[0])
else:
df_filled[col] = df_filled[col].fillna('缺失')
else: # 数值列
# 用中位数填充(对异常值更稳健)
df_filled[col] = df_filled[col].fillna(df_filled[col].median())
return df_filled
df_filled = fill_missing_values(df)
print("智能填充结果:")
print(df_filled)
实际业务案例:销售数据
# 模拟销售数据
sales_data = pd.DataFrame({
'日期': pd.date_range('2023-01-01', periods=10),
'销售额': [100, 150, np.nan, 200, np.nan, 250, 300, np.nan, 350, 400],
'客户数': [10, 12, 11, np.nan, 15, 16, np.nan, 18, 19, 20]
})
# 策略:销售额用前一周均值填充,客户数用线性填充
sales_data['销售额'] = sales_data['销售额'].fillna(
sales_data['销售额'].rolling(window=3, min_periods=1).mean()
)
sales_data['客户数'] = sales_data['客户数'].interpolate(method='linear')
print(sales_data)
选择策略的建议
| 数据类型 | 推荐填充方法 | 原因 |
|---|---|---|
| 数值连续 | 均值/中位数/插值 | 保持数据分布 |
| 数值离散 | 众数/中位数 | 不引入不合理值 |
| 分类数据 | 众数/新建"缺失"类别 | 不改变类别含义 |
| 时间序列 | 向前填充/插值 | 保持时间连续性 |
| 少量缺失 | 删除行 | 简单有效 |
| 大量缺失 | 算法预测(KNN等) | 利用多变量信息 |
核心原则:
- 缺失率 < 5%:直接删除或均值填充
- 缺失率 5-20%:根据数据类型选择合适方法
- 缺失率 > 20%:谨慎处理,可能需要更复杂的模型
如果需要处理真实数据,建议先分析缺失模式(随机缺失/非随机缺失),再选择最适合的方法。