MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python通过Pandas处理缺失数据

2023-12-027.3k 阅读

认识缺失数据

在数据分析和处理过程中,缺失数据是一个常见且棘手的问题。缺失数据可能以多种形式出现,它们的存在会影响到数据分析结果的准确性和可靠性。理解缺失数据产生的原因、其在数据集中的表现形式,是我们有效处理缺失数据的关键前提。

缺失数据产生的原因

  1. 数据收集过程中的遗漏:在进行问卷调查、传感器数据采集等活动时,由于各种原因,部分数据可能没有被成功记录。例如,受访者可能遗漏某些问题未作答,传感器可能在某一时刻出现故障,导致数据缺失。
  2. 数据转换和传输错误:当数据从一个系统转移到另一个系统,或者在不同格式之间进行转换时,可能会出现数据丢失的情况。比如从一种数据库格式转换到另一种时,某些不兼容的数据字段可能被丢弃。
  3. 数据录入错误:人工录入数据时,难免会出现疏忽,忘记填写某些值,从而导致缺失数据。

缺失数据在数据集中的表现形式

  1. 数值型数据的缺失:在数值型数据列中,缺失值通常用特殊的占位符表示,在Python的Pandas库中,常见的是NaN(Not a Number)。例如,在记录员工工资的列中,如果某个员工的工资数据缺失,就可能显示为NaN
  2. 对象型数据的缺失:对于对象型数据,如字符串类型的数据列,缺失值也可能表现为NaN。但有时也可能用空字符串''来表示缺失。比如在记录客户地址的列中,若地址信息缺失,可能显示为NaN或空字符串。

Pandas中缺失数据的识别

Pandas提供了一系列方法来识别数据集中的缺失值,这些方法能够帮助我们快速定位和了解缺失数据的分布情况。

使用isnull()方法

isnull()方法用于检测数据中的缺失值,它会返回一个与原数据形状相同的布尔型数据,其中缺失值对应的位置为True,非缺失值对应的位置为False

import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
print(df.isnull())

上述代码创建了一个简单的DataFrame,并使用isnull()方法检测缺失值,输出结果如下:

    col1   col2
0  False  False
1   True  False
2  False   True

使用notnull()方法

notnull()方法与isnull()方法相反,它返回的布尔型数据中,非缺失值对应的位置为True,缺失值对应的位置为False

import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
print(df.notnull())

输出结果为:

    col1   col2
0   True   True
1  False   True
2   True  False

统计缺失值的数量

我们可以结合isnull()notnull()方法与sum()方法来统计每列缺失值的数量。

import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
print(df.isnull().sum())

输出结果会显示每列缺失值的个数:

col1    1
col2    1
dtype: int64

缺失数据的处理方法

处理缺失数据的方法有多种,主要可以分为删除缺失数据、填补缺失数据以及使用模型预测缺失数据等几类。下面我们详细介绍这些方法及其在Pandas中的实现。

删除缺失数据

  1. 删除包含缺失值的行:使用dropna()方法,默认情况下,dropna()会删除任何包含缺失值的行。
import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
new_df = df.dropna()
print(new_df)

上述代码执行后,包含缺失值的行被删除,输出结果为:

   col1 col2
0     1    a
  1. 删除包含缺失值的列:通过设置axis = 1,可以删除包含缺失值的列。
import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
new_df = df.dropna(axis = 1)
print(new_df)

输出结果只保留了没有缺失值的列:

   col1
0     1
1  NaN
2     3
  1. 按阈值删除:可以通过设置thresh参数,仅删除缺失值数量超过一定阈值的行或列。例如,设置thresh = 2,表示仅删除缺失值数量大于等于2的行。
import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None], 'col3': [None, None, None]}
df = pd.DataFrame(data)
new_df = df.dropna(thresh = 2)
print(new_df)

在上述示例中,只有第三行缺失值数量大于等于2,所以第三行被删除,输出结果为:

   col1 col2 col3
0     1    a  NaN
1  NaN    b  NaN

填补缺失数据

  1. 使用常数填补:使用fillna()方法,可以用指定的常数填补缺失值。
import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
new_df = df.fillna(0)
print(new_df)

上述代码将所有缺失值用0填补,输出结果为:

   col1 col2
0  1.0    a
1  0.0    b
2  3.0  0.0
  1. 使用前向填充(ffill)ffill会使用前一个非缺失值来填补当前缺失值。
import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
new_df = df.fillna(method='ffill')
print(new_df)

输出结果中,col1列的第二个缺失值用第一个值1填补,col2列的第三个缺失值用第二个值b填补:

   col1 col2
0  1.0    a
1  1.0    b
2  3.0    b
  1. 使用后向填充(bfill)bfill则是使用后一个非缺失值来填补当前缺失值。
import pandas as pd

data = {'col1': [1, None, 3], 'col2': ['a', 'b', None]}
df = pd.DataFrame(data)
new_df = df.fillna(method='bfill')
print(new_df)

输出结果中,col1列的第二个缺失值用第三个值3填补,col2列的第三个缺失值没有后一个非缺失值,所以仍为NaN

   col1 col2
0  1.0    a
1  3.0    b
2  3.0  NaN
  1. 使用统计量填补:可以使用均值、中位数、众数等统计量来填补数值型数据的缺失值。
import pandas as pd

data = {'col1': [1, None, 3], 'col2': [4, None, 6]}
df = pd.DataFrame(data)
mean_value = df['col1'].mean()
new_df = df.fillna({'col1': mean_value})
print(new_df)

上述代码计算col1列的均值,并使用均值填补该列的缺失值。对于对象型数据,可以使用众数填补。

import pandas as pd

data = {'col1': ['a', None, 'c'], 'col2': ['d', 'e', None]}
df = pd.DataFrame(data)
mode_value = df['col1'].mode()[0]
new_df = df.fillna({'col1': mode_value})
print(new_df)

这里计算col1列的众数,并使用众数填补该列的缺失值。

使用模型预测缺失数据

  1. 简单线性回归模型预测数值型缺失值:可以使用scikit - learn库中的线性回归模型来预测数值型数据的缺失值。首先,我们需要准备好训练数据,将非缺失值的数据作为训练集,训练一个线性回归模型,然后用该模型预测缺失值。
import pandas as pd
from sklearn.linear_model import LinearRegression
import numpy as np

data = {'col1': [1, 2, None, 4], 'col2': [5, 6, 7, 8]}
df = pd.DataFrame(data)
# 提取非缺失值数据
train_data = df.dropna()
X_train = train_data[['col2']]
y_train = train_data['col1']
# 训练线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)
# 预测缺失值
missing_data = df[df['col1'].isnull()][['col2']]
predicted_values = model.predict(missing_data)
df.loc[df['col1'].isnull(), 'col1'] = predicted_values
print(df)
  1. 分类模型预测对象型缺失值:对于对象型数据的缺失值预测,可以使用分类模型,如决策树分类器。同样,先准备训练数据,训练模型后进行预测。
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
import numpy as np

data = {'col1': ['a', 'b', None, 'd'], 'col2': [1, 2, 3, 4]}
df = pd.DataFrame(data)
# 提取非缺失值数据
train_data = df.dropna()
X_train = train_data[['col2']]
y_train = train_data['col1']
# 训练决策树分类器
model = DecisionTreeClassifier()
model.fit(X_train, y_train)
# 预测缺失值
missing_data = df[df['col1'].isnull()][['col2']]
predicted_values = model.predict(missing_data)
df.loc[df['col1'].isnull(), 'col1'] = predicted_values
print(df)

处理缺失数据时的注意事项

  1. 数据量与缺失比例:如果数据集非常大,少量的缺失数据可能对整体分析影响不大,删除缺失数据可能是一个简单有效的方法。但如果缺失比例较高,删除缺失数据可能会导致大量有价值信息丢失,此时填补或预测缺失数据可能更为合适。
  2. 数据类型与分布:不同的数据类型适用不同的处理方法。对于数值型数据,使用统计量填补或模型预测较为常见;对于对象型数据,使用众数填补或分类模型预测更合适。同时,要考虑数据的分布情况,例如如果数据分布不均匀,使用均值填补可能会引入较大偏差,此时中位数可能是更好的选择。
  3. 对分析结果的影响:在处理缺失数据后,需要重新评估分析结果的准确性和可靠性。不同的处理方法可能会导致分析结果的差异,尤其是在进行统计分析、建模等任务时,要确保处理缺失数据的方法不会对最终结论产生误导。

在实际的数据分析和处理工作中,深入理解并灵活运用Pandas处理缺失数据的方法,结合具体的数据特点和分析需求,选择最合适的处理策略,是保证数据分析质量的关键。通过不断实践和总结经验,我们能够更好地应对缺失数据带来的挑战,从数据中挖掘出更准确、有价值的信息。