数据清理秘籍:Pandas 一站式上手指南
大家好,这篇文章是献给那些被数据搞得头秃的朋友们!🤯 今天我们聊聊数据清理——数据分析中最基础却最不可忽视的一环。如果你刚接触 Pandas,不知道怎么处理那些坑爹的缺失值、重复数据或者奇奇怪怪的格式,别急,我来了!这篇文章会以轻松的方式手把手教你,让你化身数据清理小能手!🎉
缺失值处理
数据里有空值?别慌,这种事再正常不过了,就像喝奶茶总会有珍珠卡吸管一样。
import pandas as pd
import numpy as np
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', None],
'age': [25, np.nan, 30, 35, 28],
'score': [85, 90, np.nan, 75, 88]
}
df = pd.DataFrame(data)
print(df)
输出:
name age score
0 Alice 25.0 85.0
1 Bob NaN 90.0
2 Charlie 30.0 NaN
3 David 35.0 75.0
4 None 28.0 88.0
填充缺失值
- 用均值填充:
df['age'].fillna(df['age'].mean(), inplace=True)
注意事项:
- 填充前请确保列的数据类型是数字类型,否则会报错。
inplace=True会直接修改原 DataFrame,如果不希望修改原数据,可以省略此参数并将结果赋值给新变量。
- 用固定值填充:
df['name'].fillna('Unknown', inplace=True)
注意事项:
- 填充字符串时,注意统一格式(如大小写、空格)。
- 填充后的值可能影响后续的分析,例如统计姓名的唯一值时会包含
'Unknown'。
删除缺失值
df.dropna(subset=['score'], inplace=True)
注意事项:
subset参数指定需要检查缺失值的列,默认检查所有列。- 删除行后,索引不会自动重置,可能需要
df.reset_index(drop=True, inplace=True)。
💡 小贴士:填充还是删除,取决于你对数据的理解,盲删可能会失去重要信息。
处理重复数据
有时候,你会发现数据像复制粘贴一样重复出现,清理起来其实不难。
data = {'name': ['Alice', 'Bob', 'Alice'], 'age': [25, 30, 25]}
df = pd.DataFrame(data)
- 找到重复行:
print(df.duplicated())
输出:
0 False
1 False
2 True
注意事项:
- 默认检查所有列,如果只想检查部分列,可以使用
df.duplicated(subset=['name'])。 - 返回的是布尔值序列,可以结合过滤器使用:
df[df.duplicated()]。
- 删除重复行:
df.drop_duplicates(inplace=True)
注意事项:
- 默认保留第一个出现的重复值,如果想保留最后一个,可以加
keep='last'。 - 删除后同样需要注意索引是否需要重置。
数据类型转换
数据类型搞错了,程序报错是分分钟的事,比如年龄竟然是字符串,这谁顶得住?
data = {'age': ['25', '30', '35']}
df = pd.DataFrame(data)
df['age'] = df['age'].astype(int) # 转换为整数
注意事项:
- 转换前请检查数据是否存在非数字字符,否则会报错。
- 如果数据中有非数字字符,可以用
pd.to_numeric(errors='coerce')来安全转换:
df['age'] = pd.to_numeric(df['age'], errors='coerce')
非数字的值会被转换为 NaN。
标准化数据格式
有些人日期写成 2024-01-01,有些人写成 01/01/2024,清理起来头都大了。
data = {'date': ['2024-01-01', '01/01/2024', '2024/01/01']}
df = pd.DataFrame(data)
df['date'] = pd.to_datetime(df['date'])
print(df)
输出:
date
0 2024-01-01
1 2024-01-01
2 2024-01-01
🎉 一行代码解决大问题!
注意事项:
- Pandas 会自动识别大多数常见日期格式,但如果格式很特殊,可以用
format参数明确指定。 - 如果转换失败,可以用
errors='coerce'让无法解析的日期变为 NaT。
处理异常值
数据里蹦出个 9999?这显然是程序员调皮留下的!
data = {'age': [25, 30, 35, 9999]}
df = pd.DataFrame(data)
df.loc[df['age'] > 100, 'age'] = df['age'].median() # 用中位数替换
注意事项:
- 识别异常值的规则要根据业务逻辑决定,别随便拍脑袋定一个阈值。
- 替换异常值时,中位数和均值是常见选择,但要注意异常值可能对均值的计算有影响。
数据分箱
要把年龄按区间分组,比如 0-18,18-30,30-50?没问题!
df['age_group'] = pd.cut(df['age'], bins=[0, 18, 30, 50], labels=['少年', '青年', '中年'])
print(df)
注意事项:
bins参数需要覆盖所有可能的值,否则会有 NaN 出现。- 如果数据中有负值或超出范围的值,也会被标记为 NaN。
数据合并
有多个表?合并它们!
data1 = {'id': [1, 2], 'name': ['Alice', 'Bob']}
data2 = {'id': [1, 2], 'score': [85, 90]}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
merged_df = pd.merge(df1, df2, on='id')
print(merged_df)
输出:
id name score
0 1 Alice 85
1 2 Bob 90
注意事项:
- 默认是内连接(
how='inner'),如果想保留左表或右表所有数据,可以使用左连接或右连接:how='left'或how='right'。 - 如果有多个列需要匹配,可以通过
on=['col1', 'col2']指定。
删除不需要的列
数据中有些列完全无用,删掉!
df.drop(columns=['unnecessary_column'], inplace=True)
注意事项:
- 如果列名不存在,会报错,可以用
errors='ignore'忽略。 - 一次删除多列时,
columns参数接受列表:columns=['col1', 'col2']。
数据分组与聚合
需要统计每个组的平均值?简单!
data = {'team': ['A', 'A', 'B', 'B'], 'score': [85, 90, 75, 80]}
df = pd.DataFrame(data)
result = df.groupby('team')['score'].mean()
print(result)
输出:
team
A 87.5
B 77.5
Name: score, dtype: float64
注意事项:
groupby返回的是一个分组对象,操作后需要用.reset_index()转换回 DataFrame。- 聚合操作可以使用多个函数,比如
agg(['mean', 'sum'])。
处理文本数据
有一列是乱七八糟的文本,比如大小写不统一、空格太多?Pandas 是你的好帮手!
data = {'text': [' hello ', 'WORLD', 'pandas']}
df = pd.DataFrame(data)
df['text_cleaned'] = df['text'].str.strip().str.lower()
print(df)
输出:
text text_cleaned
0 hello hello
1 WORLD world
2 pandas pandas
注意事项:
str属性仅适用于字符串列,非字符串列会报错。- 常用操作还有
.str.replace()和.str.contains(),可以进一步清理数据。
这就是 Pandas 数据清理的基本功啦!💪 用好这些方法,你就能从脏乱的数据中提取出干净的信息。最后的建议是,多练习多思考,祝你在数据世界里玩的开心!🎉