Pandas 数据清理完全指南:从入门到精通的十大技巧,让你的分析效率提升10倍!

238 阅读5分钟

数据清理秘籍: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)

注意事项

  1. 填充前请确保列的数据类型是数字类型,否则会报错。
  2. inplace=True 会直接修改原 DataFrame,如果不希望修改原数据,可以省略此参数并将结果赋值给新变量。
  • 用固定值填充:
df['name'].fillna('Unknown', inplace=True)

注意事项

  1. 填充字符串时,注意统一格式(如大小写、空格)。
  2. 填充后的值可能影响后续的分析,例如统计姓名的唯一值时会包含 'Unknown'

删除缺失值

df.dropna(subset=['score'], inplace=True)

注意事项

  1. subset 参数指定需要检查缺失值的列,默认检查所有列。
  2. 删除行后,索引不会自动重置,可能需要 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

注意事项

  1. 默认检查所有列,如果只想检查部分列,可以使用 df.duplicated(subset=['name'])
  2. 返回的是布尔值序列,可以结合过滤器使用:df[df.duplicated()]
  • 删除重复行:
df.drop_duplicates(inplace=True)

注意事项

  1. 默认保留第一个出现的重复值,如果想保留最后一个,可以加 keep='last'
  2. 删除后同样需要注意索引是否需要重置。

数据类型转换

数据类型搞错了,程序报错是分分钟的事,比如年龄竟然是字符串,这谁顶得住?

data = {'age': ['25', '30', '35']}
df = pd.DataFrame(data)
df['age'] = df['age'].astype(int)  # 转换为整数

注意事项

  1. 转换前请检查数据是否存在非数字字符,否则会报错。
  2. 如果数据中有非数字字符,可以用 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

🎉 一行代码解决大问题!

注意事项

  1. Pandas 会自动识别大多数常见日期格式,但如果格式很特殊,可以用 format 参数明确指定。
  2. 如果转换失败,可以用 errors='coerce' 让无法解析的日期变为 NaT。

处理异常值

数据里蹦出个 9999?这显然是程序员调皮留下的!

data = {'age': [25, 30, 35, 9999]}
df = pd.DataFrame(data)
df.loc[df['age'] > 100, 'age'] = df['age'].median()  # 用中位数替换

注意事项

  1. 识别异常值的规则要根据业务逻辑决定,别随便拍脑袋定一个阈值。
  2. 替换异常值时,中位数和均值是常见选择,但要注意异常值可能对均值的计算有影响。

数据分箱

要把年龄按区间分组,比如 0-18,18-30,30-50?没问题!

df['age_group'] = pd.cut(df['age'], bins=[0, 18, 30, 50], labels=['少年', '青年', '中年'])
print(df)

注意事项

  1. bins 参数需要覆盖所有可能的值,否则会有 NaN 出现。
  2. 如果数据中有负值或超出范围的值,也会被标记为 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

注意事项

  1. 默认是内连接(how='inner'),如果想保留左表或右表所有数据,可以使用左连接或右连接:how='left'how='right'
  2. 如果有多个列需要匹配,可以通过 on=['col1', 'col2'] 指定。

删除不需要的列

数据中有些列完全无用,删掉!

df.drop(columns=['unnecessary_column'], inplace=True)

注意事项

  1. 如果列名不存在,会报错,可以用 errors='ignore' 忽略。
  2. 一次删除多列时,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

注意事项

  1. groupby 返回的是一个分组对象,操作后需要用 .reset_index() 转换回 DataFrame。
  2. 聚合操作可以使用多个函数,比如 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

注意事项

  1. str 属性仅适用于字符串列,非字符串列会报错。
  2. 常用操作还有 .str.replace().str.contains(),可以进一步清理数据。

这就是 Pandas 数据清理的基本功啦!💪 用好这些方法,你就能从脏乱的数据中提取出干净的信息。最后的建议是,多练习多思考,祝你在数据世界里玩的开心!🎉