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())
处理缺失值,常用的就三招:
- 直接删除 —— 如果缺失行很少,删了不心疼
- 填充 —— 用均值、中位数、众数填上
- 插值 —— 用前后值推算,适合时间序列
举个例子:
# 删除所有包含缺失值的行
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 数据清洗流程总览
为了让你对整个清洗流程有个整体认识,我画了一张图:
这张图很直观:原始数据进来,先查缺失值,再处理重复值,最后做类型转换。三步走完,数据就干净了。
一个小技巧:清洗完数据后,记得用 df.describe() 看一眼统计摘要。如果发现最大值、最小值明显异常,那可能还有脏数据没处理干净。
好了,数据清洗就讲到这里。记住,清洗不是一次性的活。每次拿到新数据,都要走一遍这个流程。习惯成自然。