数据预处理方法大全+实战代码(二)

前言

本文详细介绍缺失值处理异常值检测数据一致性处理。这是数据清洗的第一步,关键步骤。

1、缺失值类型

缺失值可分为三种类型:

  • 完全随机缺失(MCAR):缺失完全随机,与其他变量无关。缺失的发生是完全随机的,没有可预测的规律或趋势。

  • 随机缺失(MAR):缺失与其他变量有关,但与缺失数据本身的值无关。例如,在一个调查问卷中,如果男性比女性更倾向于不回答某个问题,那么这个缺失就与性别这个变量有关。

  • 非随机缺失(MNAR):缺失与缺失变量本身的值有关。

2、判断缺失值类型

可以使用可视化分析或统计检验方法。

2.1 统计检验方法

回顾下统计检验方法的定义、基本概念、常见类型

  • 定义:统计检验是统计学中用于判断数据是否支持某个假设的方法。它通过计算统计量和对应的p值来评估样本数据与假设之间的差异。

  • 基本概念

    • 假设原假设(H0)表示没有显著差异或效应的假设。例如,在t检验中,原假设通常是两个总体均值相等。 备择假设(H1 或 Ha):表示存在显著差异或效应的假设。例如,在t检验中,备择假设可能是两个总体均值不相等。
  • 显著差异:两个样本在某个统计量(如均值,中位数等)上存在显著的差别。这种差别不太可能是由于随机误差或抽样误差导致的。

  • 统计量:衡量样本数据与假设之间的差异。常见的统计量包括t统计量F统计量卡方统计量等。

  • p值:p值越小,表示样本数据与原假设之间的差异越显著。

  • 显著性水平(α):事先设定的阈值,如0.05、0.01等。若p<α,则拒绝H0。

2.2 常见统计检验类型

  • t检验:用于比较两个样本均值的差异。用于连续变量

  • 方差分析(ANOVA):用于比较三个或更多样本均值的差异。用于连续变量

  • 卡方检验:用于检验分类变量之间的独立性或拟合优度。

  • 回归分析:用于检验变量之间的线性关系。用于连续变量

  • 非参数检验:如Wilcoxon秩和检验、Kruskal-Wallis检验等,用于不满足参数检验假设的数据。

独立样本T检验的代码示例

import pandas as pd
import numpy as np
from scipy.stats import ttest_ind

# 创建一个示例数据集
data = {
    'A': [1, 2, 3, 4, 5, np.nan, 7, 8, 9, 10],
    'B': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
    'C': [np.nan, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
}
df = pd.DataFrame(data)

# 判断A列的缺失值类型
# 检查A列缺失值与其他变量的关系
missing_a = df[df['A'].isnull()]
non_missing_a = df[df['A'].notnull()]

# 对B列进行t检验
t_stat, p_value = ttest_ind(missing_a['B'], non_missing_a['B'], nan_policy='omit')
print(f"A列缺失值与B列的关系t检验结果:t统计量={t_stat:.4f}, p值={p_value:.4f}")

# 对C列进行t检验
t_stat, p_value = ttest_ind(missing_a['C'], non_missing_a['C'], nan_policy='omit')
print(f"A列缺失值与C列的关系t检验结果:t统计量={t_stat:.4f}, p值={p_value:.4f}")

# 如果A列缺失值与其他变量的p值均大于显著性水平(如0.05),则可能是MCAR
# 如果A列缺失值与其他变量的p值小于显著性水平,则可能是MAR
# 如果A列缺失值与其他变量的p值小于显著性水平,且缺失值与A列本身值有关,则可能是MNAR

SciPy是一个开源的Python库,建立在NumPy库之上,提供了大量的数学算法和工具,代码里SciPy包的模块用到scipy.stats统计函数,里面很多stats.mstats API

T检验函数:ttest_ind(a, b, axis=0, equal_var=True, alternative='two-sided')。

2.3 Python中查询缺失值

Pandas为例,DataFrame 中NaN。可以分为三种:

  • 缺失值,三种写法:np.nan(Not a Number) 、 Nonepd.NaT(时间格式的空值,注意大小写不能错)。
  • 空值:空字符串""
  • 还有导入的Excel,表示缺失值的字符-等。

接下来进行用Python查询缺失值:

最常用的⽅法

  • isnull(),返回True表示此处为缺失值
  • any()⽅法搭配使用来查询存在缺失值的行
  • sum()⽅法搭配使用来查询存在缺失值的列
df.isnull()  # 缺失值为True
df.isnull().any(axis=1) # 缺失值的行为True
df.isnull().sum()  # 缺失值的列为1
df[df.isnull().values==True]  #输出为有缺失值的行
df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False) # 删除空值

isna()和isnull()的用法相同

查询字符-,用正则表达式

import re
df[df["C列"].apply(lambda x: len(re.findall('NA|[*|?|!|#|-]', x)) != 0)]

df.apply()函数可以用于对DataFrame的行或列应用一个函数。lambda函数是一种简洁的匿名函数定义方式,常与apply()一起使用,以便在数据处理中快速定义和应用简单的函数。如df.apply(lambda row: row['A'] + row['B'] + row['C'], axis=1)对每行求和,df.apply(lambda x: x * 2)对每列的值乘2,不用循环函数了。

3、缺失值填补

3.1 均值/中位数/众数填充与插值方法

  • a) 均值填充:公式:x̄ = (Σx_i) / n
    原理:用变量的平均值填充缺失值。适用于正态分布的数据,但可能会降低数据的变异性。

  • b) 中位数填充:公式:中位数 = 将数据排序后的中间值
    原理:用变量的中位数填充缺失值。对异常值不敏感,适用于偏态分布数据

  • c) 众数填充:公式:众数 = 出现频率最高的值
    原理:用变量中出现最频繁的值填充缺失值。适用于分类变量

3.2 Python中sklearnpandas实现均值/中位数/众数填充

最简单的是df.fillna(value),使用指定的值(如均值、中位数、众数等)填充缺失值。

SimpleImputerscikit-learn 库中的一个类,用于对缺失数据进行填充。它可以根据指定的策略来填充缺失值,如 mean(均值)、median(中位数)、most_frequent(众数)或 constant(常数)。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.impute import SimpleImputer
# 创建示例数据集
np.random.seed(42)
df = pd.DataFrame({
    'A': np.random.randn(100),
    'B': np.random.randn(100),
    'C': np.random.randn(100)
})
df.loc[np.random.choice(df.index, 20), 'A'] = np.nan
df.loc[np.random.choice(df.index, 20), 'B'] = np.nan
df.loc[np.random.choice(df.index, 20), 'C'] = np.nan

# 不同填充方法
methods = ['mean', 'median', 'most_frequent']
imputed_dfs = {}
for method in methods:
    imputer = SimpleImputer(strategy=method)
    imputed_dfs[method] = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)

# 可视化比较
plt.figure(figsize=(15, 5))
for i, (name, imputed_df) in enumerate([('Original', df)] + [(m, imputed_dfs[m]) for m in methods]):
    plt.subplot(1, 4, i + 1)
    plt.scatter(imputed_df['A'], imputed_df['B'], alpha=0.5)
    plt.title(f'{name.capitalize()} Imputation')
    plt.xlabel('Feature A')
    plt.ylabel('Feature B')

plt.tight_layout()
plt.show()

结果如下,


原始数据、均值填充、中位数填充、众数填充
# 统计比较
for name, imputed_df in [('Original', df)] + [(m, imputed_dfs[m]) for m in methods]:
    print(f"\n{name.capitalize()} Imputation Statistics:")
    print(imputed_df.describe())

结果比较:

3.3 基于模型的缺失值填补(如KNN、MICE)

  • a) KNN(K-最近邻)填充

    • 原理:找到与缺失值样本最相似的K个样本,用这些样本的平均值填充。

    • 算法步骤

      (1)计算所有样本间的距离(如欧氏距离)
      (2)选择K个最近的邻居
      (3)用这K个邻居的平均值填充缺失值

  • b) MICE(多重插补链式方程)

    • 原理:使用其他变量的信息来预测缺失值,通过多次迭代来改善估计。

    • 算法步骤

      (1)用简单方法(如均值)填充所有缺失值
      (2)选择一个有缺失值的变量,将其他变量作为预测变量
      (3)使用回归模型预测缺失值
      (4)重复步骤2-3,直到所有变量都被处理
      (5)重复多次整个过程,生成多个完整数据集

3.4 Python中sklearn实现KNN、MICE填充

import pandas as pd
import numpy as np
from sklearn.impute import KNNImputer
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
import matplotlib.pyplot as plt

# 创建示例数据集
np.random.seed(42)
df = pd.DataFrame({
    'A': np.random.randn(100),
    'B': np.random.randn(100),
    'C': np.random.randn(100)
})
df.loc[np.random.choice(df.index, 20), 'A'] = np.nan
df.loc[np.random.choice(df.index, 20), 'B'] = np.nan
df.loc[np.random.choice(df.index, 20), 'C'] = np.nan

# KNN填充
knn_imputer = KNNImputer(n_neighbors=5)
df_knn = pd.DataFrame(knn_imputer.fit_transform(df), columns=df.columns)

# MICE填充
mice_imputer = IterativeImputer(random_state=0)
df_mice = pd.DataFrame(mice_imputer.fit_transform(df), columns=df.columns)

# 可视化比较
plt.figure(figsize=(15, 5))
for i, (name, imputed_df) in enumerate([('Original', df), ('KNN', df_knn), ('MICE', df_mice)]):
    plt.subplot(1, 3, i + 1)
    plt.scatter(imputed_df['A'], imputed_df['B'], alpha=0.5)
    plt.title(f'{name} Imputation')
    plt.xlabel('Feature A')
    plt.ylabel('Feature B')

plt.tight_layout()
plt.show()

# 统计比较
for name, imputed_df in [('Original', df), ('KNN', df_knn), ('MICE', df_mice)]:
    print(f"\n{name} Imputation Statistics:")
    print(imputed_df.describe())

结果不做过多介绍,请各位自行测试。

4、总结

  • 缺失值类型、如何判断缺失值类型
  • Pandas中缺失值的表现方式,代码查询的方法
  • 缺失值填充,用均值、中位数、KNN等等,展示代码
  • 这里列一些Python中数据处理常用的包、用法,自行学习吧,非常有用的。
    • Pandas包、Numpy包、Scipy包、Sklearn包、Matplotlib
    • df.apply()lambda函数结合使用
    • df.apply()groupby()的结合使用
    • enumerate的用法,它是一个迭代器
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容