4、数据清洗入门:处理缺失值、重复值,数据类型转换,Pandas常用清洗函数

数据清洗,说白了就是给数据「洗澡」。

我做了这么多年数据可视化,发现一个残酷的事实:80% 的时间都花在洗数据上。你想想看,如果原始数据里一堆空值、重复行、类型还不对,那后面画出来的图能看吗?

嗯,这节课我们就来搞定这件事。我会带着你,用 Pandas 把数据洗得干干净净。

核心思想:脏数据进,干净数据出。清洗不是炫技,是基本功。

4.1 缺失值处理:别让空值毁了你的图

缺失值,就是表格里那些空着的格子。在 Pandas 里用 NaN 表示。

我个人习惯,拿到数据第一件事就是看看缺失情况:

import pandas as pd

# 读取数据
df = pd.read_csv('emotion_data.csv')

# 看看每列有多少缺失值
print(df.isnull().sum())

# 或者更直观一点
print(df.info())

处理缺失值,常用的就三招:

  1. 直接删除 —— 如果缺失行很少,删了不心疼
  2. 填充 —— 用均值、中位数、众数填上
  3. 插值 —— 用前后值推算,适合时间序列

举个例子:

# 删除所有包含缺失值的行
df_clean = df.dropna()

# 用均值填充某一列
df['score'].fillna(df['score'].mean(), inplace=True)

# 用前一个值填充(适合时间序列)
df['value'].fillna(method='ffill', inplace=True)

我的经验:情绪数据里,如果某条记录的「情绪标签」缺失,我一般直接删掉。因为标签是核心,猜出来的不准。但如果是「年龄」这种辅助字段缺失,用中位数填就行。

4.2 重复值处理:别让数据「分身」

重复值,就是一模一样的行出现了多次。这在数据采集时很常见。

我曾经遇到过一个项目,因为爬虫脚本没去重,结果情绪数据里同一个人的记录重复了 5 次。画出来的趋势图直接变形了。

# 检查重复行
print(df.duplicated().sum())

# 查看具体的重复行
print(df[df.duplicated()])

# 删除重复行(保留第一次出现的)
df_unique = df.drop_duplicates()

# 也可以指定列来判断重复
df_unique = df.drop_duplicates(subset=['user_id', 'date'])

注意:不是所有重复都要删。比如同一个用户在不同时间点的记录,虽然 user_id 重复,但日期不同,那就是正常数据。别一刀切。

4.3 数据类型转换:让数据「对号入座」

数据类型不对,是新手最容易踩的坑。

你想想看,如果「年龄」这一列存的是字符串,那你怎么算平均年龄?如果「日期」存的是文本,那你怎么按时间排序?

常见的转换场景:

原始类型 目标类型 常用方法
字符串 → 数值 int / float pd.to_numeric()
字符串 → 日期 datetime pd.to_datetime()
数值 → 分类 category astype('category')

看个实际例子:

# 字符串转数值(遇到错误就变成NaN)
df['age'] = pd.to_numeric(df['age'], errors='coerce')

# 字符串转日期
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')

# 数值转分类(比如情绪等级)
df['level'] = df['level'].astype('category')

避坑指南:我曾经遇到一个 CSV 文件,里面「收入」列有逗号(比如 "1,234"),直接转数值会报错。解决办法是先去掉逗号:df['income'] = df['income'].str.replace(',', ''),再转数值。

4.4 Pandas 常用清洗函数一览

上面讲的是具体场景,这里我整理一个常用函数清单,方便你查阅:

函数 作用 示例
isnull() 检查缺失值 df.isnull().sum()
dropna() 删除缺失值 df.dropna(axis=0)
fillna() 填充缺失值 df.fillna(0)
duplicated() 检查重复值 df.duplicated()
drop_duplicates() 删除重复值 df.drop_duplicates()
to_numeric() 转数值类型 pd.to_numeric()
to_datetime() 转日期类型 pd.to_datetime()
astype() 强制类型转换 df['col'].astype('float')
replace() 替换值 df.replace('男', 'M')
rename() 重命名列 df.rename(columns={'旧名':'新名'})

我的建议:把这几个函数记熟,能解决 90% 的清洗问题。剩下的 10%,遇到再查文档也不迟。

4.5 数据清洗流程总览

为了让你对整个清洗流程有个整体认识,我画了一张图:

数据清洗流程 原始数据 检查缺失值 处理重复值 数据类型转换 ↓ 检查 NaN ↓ 删除或填充 ↓ 去重 ↓ 转数值/日期/分类 清洗流程

这张图很直观:原始数据进来,先查缺失值,再处理重复值,最后做类型转换。三步走完,数据就干净了。

一个小技巧:清洗完数据后,记得用 df.describe() 看一眼统计摘要。如果发现最大值、最小值明显异常,那可能还有脏数据没处理干净。

好了,数据清洗就讲到这里。记住,清洗不是一次性的活。每次拿到新数据,都要走一遍这个流程。习惯成自然。


专注资料整理