数据清洗流程与技巧

#王者杯·14天创作挑战营·第5期#

数据清洗是指对原始数据进行系统性的审查、校验与修正,旨在识别并处理其中存在的错误、不一致、不完整、重复和无效的部分。该过程的核心目标,是生成高质量、可信赖的“干净”数据,为后续的数据分析与建模奠定准确、一致的基础。

数据清洗并非一系列彼此孤立的操作,而是需要遵循一套系统化且循环迭代的科学流程。这一流程构建起了一个从问题诊断直至效果验证的完整闭环。

一、数据质量评估与探索

在对原始数据进行清洗之前,首先需要对其质量进行全面且系统的评估,明确数据中存在的具体问题,例如缺失值、重复值、异常值以及不一致性等。只有在准确诊断问题的基础上,才能制定出具有针对性的清洗策略。

(1)数据概览与结构分析

使用.info()方法快速获取数据集的整体情况:

import pandas as pd



# 读取数据

df = pd.read_csv('用户订单原始数据.csv')



# 查看数据概览

print("数据集概览(info):")

print(df.info())

运行结果如下所示:

数据集概览(info):

<class 'pandas.core.frame.DataFrame'>

RangeIndex: 36 entries, 0 to 35

Data columns (total 14 columns):

 #   Column   Non-Null Count  Dtype 

---  ------   --------------  ----- 

 0   订单ID     36 non-null     int64 

 1   用户ID     36 non-null     int64 

 2   订单日期     36 non-null     object

 3   城市       36 non-null     object

 4   年龄       35 non-null     float64

 5   订单金额(元)  34 non-null     float64

 6   商品类别     36 non-null     object

 7   商品名称     36 non-null     object

 8   数量       36 non-null     int64 

 9   支付方式     36 non-null     object

 10  订单状态     36 non-null     object

 11  最后登录时间   36 non-null     object

 12  会员等级     36 non-null     object

 13  客服备注     7 non-null      object

dtypes: float64(2), int64(3), object(9)

memory usage: 4.1+ KB

None

(2)数值型字段分布与异常检测

使用.describe()方法查看数值型字段的统计描述:

print("\n数值型字段描述性统计(describe):")

print(df.describe())

运行结果如下所示:

数值型字段描述性统计(describe):

               订单ID        用户ID          年龄      订单金额(元)         数量

count     36.000000   36.000000   35.000000    34.000000  36.000000

mean   10017.527778  217.527778   37.114286   879.726471   1.222222

std       10.489413   10.489413   29.246188  1812.952159   0.540429

min    10001.000000  201.000000   22.000000   -88.500000   1.000000

25%    10008.750000  208.750000   27.000000    61.375000   1.000000

50%    10017.500000  217.500000   31.000000   299.000000   1.000000

75%    10026.250000  226.250000   37.000000   599.000000   1.000000

max    10035.000000  235.000000  200.000000  8888.000000   3.000000

(3)缺失值精确统计

通过.isnull().sum()精确计算每列的缺失值数量:

# 进行缺失值的精确统计

print("\n各字段缺失值统计:")

print(df.isnull().sum())

运行结果如下所示:

各字段缺失值统计:

订单ID        0

用户ID        0

订单日期        0

城市          0

年龄          1

订单金额(元)     2

商品类别        0

商品名称        0

数量          0

支付方式        0

订单状态        0

最后登录时间      0

会员等级        0

客服备注       29

dtype: int64

(4)重复记录检测

使用.duplicated().sum()检查完全重复的行:

# 进行重复行的统计

print(f"\n完全重复的行数:{df.duplicated().sum()}")

运行结果如下所示:

完全重复的行数:1

(5)分类型字段唯一值检查

针对分类型字段(如城市、支付方式),使用.value_counts()查看取值分布:

print("\n城市取值分布:")

print(df['城市'].value_counts())



print("\n支付方式分布:")

print(df['支付方式'].value_counts())

运行结果如下所示:

城市取值分布:

城市

北京市    5

北京     4

广州市    3

上海市    3

杭州市    3

深圳市    2

重庆市    2

武汉市    2

南京市    2

天津市    2

苏州市    2

西安市    2

深圳     1

SH     1

广州     1

成都市    1

Name: count, dtype: int64



支付方式分布:

支付方式

支付宝     11

微信支付     9

信用卡      8

借记卡      8

Name: count, dtype: int64

二、数据清洗

在完成前述系统性的数据评估后,我们已全面识别出数据集中存在的各类质量问题。接下来,将依据评估结果,针对不同问题制定并执行相应的数据清洗方案。

(1)缺失值处理

存在缺失值的字段有“年龄”、“订单金额(元)”以及“客服备注”:

  1. 其中“年龄”与“订单金额(元)”的缺失值较少,并且整体的数据分布偏斜,可以考虑使用中位数进行填充。
  2. “客服备注”字段的缺失率高达80.6%,并且分析价值较低,因此可以考虑整列删除。

缺失值的具体处理操作代码如下所示。

import pandas as pd



# 读取数据

df = pd.read_csv('用户订单原始数据.csv')



# 处理缺失值

# 先创建副本或先处理其他列,再删除备注列

df_clean = df.copy()



# 首先处理数值型字段的缺失值

# 确保中位数计算不包括NaN值

age_median = df_clean['年龄'].median()

revenue_median = df_clean['订单金额(元)'].median()



# 使用中位数来填充缺失值

df_clean['年龄'] = df_clean['年龄'].fillna(age_median)

df_clean['订单金额(元)'] = df_clean['订单金额(元)'].fillna(revenue_median)



# 最后删除客服备注列

df_clean = df_clean.drop(columns=['客服备注'])



print("处理后的数据集概览:")

print(df_clean.info())



# 保存修改后的数据

df_clean.to_csv('清理缺失值后的数据.csv', index=False)

运行结果如下所示:

<class 'pandas.core.frame.DataFrame'>

RangeIndex: 36 entries, 0 to 35

Data columns (total 13 columns):

 #   Column   Non-Null Count  Dtype 

---  ------   --------------  ----- 

 0   订单ID     36 non-null     int64 

 1   用户ID     36 non-null     int64 

 2   订单日期     36 non-null     object

 3   城市       36 non-null     object

 4   年龄       36 non-null     float64

 5   订单金额(元)  36 non-null     float64

 6   商品类别     36 non-null     object

 7   商品名称     36 non-null     object

 8   数量       36 non-null     int64 

 9   支付方式     36 non-null     object

 10  订单状态     36 non-null     object

 11  最后登录时间   36 non-null     object

 12  会员等级     36 non-null     object

dtypes: float64(2), int64(3), object(8)

memory usage: 3.8+ KB

None

(2)异常值处理

对异常值的具体处理代码如下所示:

import pandas as pd



# 读取数据

df = pd.read_csv('清理缺失值后的数据.csv')



# 创建副本

df_clean = df.copy()



print("处理前的异常值统计:")

print(f"年龄 > 100的记录: {len(df_clean[df_clean['年龄'] > 100])}条")

print(f"订单金额 < 0的记录: {len(df_clean[df_clean['订单金额(元)'] < 0])}条")



# 处理年龄异常值: 将大于100的值替换为中位数

df_clean.loc[df_clean['年龄'] > 100, '年龄'] = df_clean['年龄'].median()



# 将负值设为0(假设负值代表退款或错误)

df_clean.loc[df_clean['订单金额(元)'] < 0, '订单金额(元)'] = 0



print("\n处理后的异常值统计:")

print(f"年龄 > 100的记录: {len(df_clean[df_clean['年龄'] > 100])}条")

print(f"订单金额 < 0的记录: {len(df_clean[df_clean['订单金额(元)'] < 0])}条")



# 保存修改后的数据

df_clean.to_csv('异常值处理后的数据.csv', index=False)

运行结果如下所示:

处理前的异常值统计:
年龄 > 100的记录: 1条
订单金额 < 0的记录: 1条

处理后的异常值统计:
年龄 > 100的记录: 0条
订单金额 < 0的记录: 0条

(3)不一致值的处理

import pandas as pd

# 读取数据
df = pd.read_csv('异常值处理后的数据.csv')

# 创建副本
df_clean = df.copy()

# 处理不一致值:标准化城市名称
print("处理前的城市取值分布:")
print(df_clean['城市'].value_counts())

# 创建城市名称映射字典,将不同表达统一为标准名称
city_mapping = {
    '北京': '北京市',
    'SH': '上海市',
    '广州': '广州市',
    '深圳': '深圳市',
    # 可以继续添加其他需要标准化的映射
}

# 应用映射,标准化城市名称
df_clean['城市'] = df_clean['城市'].map(city_mapping).fillna(df_clean['城市'])

print("\n处理后的城市取值分布:")
print(df_clean['城市'].value_counts())

# 保存修改后的数据
df_clean.to_csv('清理不一致值后的数据.csv', index=False)

运行结果如下所示:

处理前的城市取值分布:
城市
北京市    5
北京     4
广州市    3
上海市    3
杭州市    3
深圳市    2
重庆市    2
武汉市    2
南京市    2
天津市    2
苏州市    2
西安市    2
深圳     1
SH     1
广州     1
成都市    1
Name: count, dtype: int64

处理后的城市取值分布:
城市
北京市    9
上海市    4
广州市    4
深圳市    3
杭州市    3
重庆市    2
武汉市    2
西安市    2
南京市    2
苏州市    2
天津市    2
成都市    1
Name: count, dtype: int64

(4)数据类型的处理

在前期数据质量评估过程中,我们发现"订单日期"与"最后登录时间"两个字段的数据类型均为Object(通常存储为字符串),而非标准的时间格式。这一情况可能源于数据采集或导入过程中的格式差异。为确保后续能够顺利进行时间序列分析、趋势统计等基于时间的深度分析,需要将这两个字段转换为datetime类型。具体的转换操作方法如下:

import pandas as pd

# 读取数据
df = pd.read_csv('清理不一致值后的数据.csv')

# 创建副本
df_clean = df.copy()

# 检查转换前的时间字段类型和样例
print("处理前的时间字段类型:")
print(df_clean[['订单日期', '最后登录时间']].dtypes)
print("\n处理前的时间字段前5条记录:")
print(df_clean[['订单日期', '最后登录时间']].head())

# 将日期时间字段从字符串转换为datetime类型
# 预处理:标准化日期字符串格式
def standardize_date_str(date_str):
    if isinstance(date_str, str):
        date_str = date_str.strip()
        if len(date_str) == 8 and date_str.isdigit():
            return f"{date_str[:4]}-{date_str[4:6]}-{date_str[6:]}"
    return date_str


df_clean['订单日期'] = df_clean['订单日期'].apply(standardize_date_str) # 格式化日期格式
# 使用errors='coerce'参数确保转换失败时返回NaT而非报错
df_clean['订单日期'] = pd.to_datetime(df_clean['订单日期'], errors='coerce') 
df_clean['最后登录时间'] = pd.to_datetime(df_clean['最后登录时间'], errors='coerce')

# 检查转换结果,查看是否有转换失败的值
print("\n转换后时间字段的缺失值情况:")
print(df_clean[['订单日期', '最后登录时间']].isnull().sum())

# 验证转换后的时间字段类型
print("\n转换后的时间字段类型:")
print(df_clean[['订单日期', '最后登录时间']].dtypes)

# 显示转换后的样例数据
print("\n转换后的时间字段前5条记录:")
print(df_clean[['订单日期', '最后登录时间']].head())

# 保存处理后的数据
df_clean.to_csv('用户订单处理后的数据.csv', index=False)
print("\n时间格式处理完成,数据已保存!")

运行效果如下所示:

处理前的时间字段类型:
订单日期      object
最后登录时间    object
dtype: object

处理前的时间字段前5条记录:
         订单日期               最后登录时间
0  2024-10-27  2024-10-27 09:15:32
1  2024/10/26  2024-10-26 14:20:18
2    20241025  2024-10-25 16:45:22
3  2024-10-24  2024-10-24 11:30:45
4  2024-10-23  2024-10-23 10:15:10

转换后时间字段的缺失值情况:
订单日期      1
最后登录时间    0
dtype: int64

转换后的时间字段类型:
订单日期      datetime64[ns]
最后登录时间    datetime64[ns]
dtype: object

转换后的时间字段前5条记录:
        订单日期              最后登录时间
0 2024-10-27 2024-10-27 09:15:32
1        NaT 2024-10-26 14:20:18
2 2024-10-25 2024-10-25 16:45:22
3 2024-10-24 2024-10-24 11:30:45
4 2024-10-23 2024-10-23 10:15:10

时间格式处理完成,数据已保存!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值