本文目录导读:

我来介绍几个使用Pandas进行数据格式清洗的典型案例:
案例1:处理缺失值
import pandas as pd
import numpy as np
# 创建示例数据
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六', None],
'年龄': [25, None, 30, 35, 28],
'工资': [8000, 9000, None, 11000, 9500],
'入职日期': ['2023-01-15', '2023/02/20', '2023-03-25', '2023-04-30', '20230505']
})
print("原始数据:")
print(df)
print("\n")
# 1. 检查缺失值
print("缺失值统计:")
print(df.isnull().sum())
# 2. 填充缺失值
# 用均值填充年龄
df['年龄'].fillna(df['年龄'].mean(), inplace=True)
# 用前向填充法填充工资
df['工资'].fillna(method='ffill', inplace=True)
# 删除包含缺失值的行
df.dropna(subset=['姓名'], inplace=True)
print("\n清洗后的数据:")
print(df)
案例2:统一日期格式
import pandas as pd
# 创建包含多种日期格式的数据
df = pd.DataFrame({
'日期': ['2023-01-15', '2023/02/20', '2023.03.25', '20230430',
'2023-05-15 14:30:00', '06/15/2023', '15-06-2023'],
'销售额': [1000, 2000, 1500, 3000, 2500, 1800, 2200]
})
print("原始日期数据:")
print(df)
# 统一日期格式为YYYY-MM-DD
def clean_date(date_str):
try:
# 尝试多种常见格式
date_formats = [
'%Y-%m-%d', # 2023-01-15
'%Y/%m/%d', # 2023/02/20
'%Y.%m.%d', # 2023.03.25
'%Y%m%d', # 20230430
'%Y-%m-%d %H:%M:%S', # 2023-05-15 14:30:00
'%m/%d/%Y', # 06/15/2023
'%d-%m-%Y' # 15-06-2023
]
for fmt in date_formats:
try:
return pd.to_datetime(date_str, format=fmt)
except:
continue
# 如果都不匹配,尝试自动解析
return pd.to_datetime(date_str)
except:
return pd.NaT
df['清洗后日期'] = df['日期'].apply(clean_date)
print("\n清洗后的日期:")
print(df[['日期', '清洗后日期']])
案例3:文本数据清洗
import pandas as pd
# 创建包含脏数据的文本数据集
df = pd.DataFrame({
'产品名称': [' 苹果iPhone 14 ', '华为 Mate 60 ', ' 小米14 Pro ',
'OPPO Find X6', ' VIVO X90 '],
'价格': ['¥5999', '¥6999元', '4,999元', '¥4499.00', '3999'],
'库存': ['100件', '50 件', '80件', '200件', '150件']
})
print("原始数据:")
print(df)
# 文本清洗函数
def clean_text_data(df):
# 1. 去除空格
df['产品名称'] = df['产品名称'].str.strip()
# 2. 清洗价格列
df['价格'] = df['价格'].str.replace('¥', '', regex=False)
df['价格'] = df['价格'].str.replace('元', '', regex=False)
df['价格'] = df['价格'].str.replace(',', '', regex=False)
df['价格'] = df['价格'].str.strip()
df['价格'] = pd.to_numeric(df['价格'], errors='coerce')
# 3. 清洗库存列
df['库存'] = df['库存'].str.replace('件', '', regex=False)
df['库存'] = df['库存'].str.strip()
df['库存'] = pd.to_numeric(df['库存'], errors='coerce')
return df
df_cleaned = clean_text_data(df.copy())
print("\n清洗后的数据:")
print(df_cleaned)
print("\n数据类型:")
print(df_cleaned.dtypes)
案例4:复杂数据清洗综合案例
import pandas as pd
import numpy as np
# 创建更复杂的脏数据集
df = pd.DataFrame({
'用户ID': ['U001', 'U002', 'U003', 'U004', 'U005', 'U006'],
'姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八'],
'邮箱': ['zhangsan@qq.com', 'lisi@163.com', 'wangwu@gmail',
'zhaoliu@.com', 'sunqi@qq.com', 'zhouba@qq.com'],
'电话': ['13800138001', '13900139002', '14000140003',
'14100141004', '14200142005', '14300143006'],
'年龄': ['25', '30岁', '35', '四十', '28', '33'],
'收入': ['8000.50', '9,000.00', '10000', '11000元', '12000', 'NaN'],
'状态': ['活跃', '不活跃', '活跃', 'active', 'inactive', 'ACTIVE']
})
print("原始数据:")
print(df)
print("\n数据类型:")
print(df.dtypes)
def comprehensive_clean(df):
cleaned_df = df.copy()
# 1. 标准化邮箱
def clean_email(email):
if pd.isna(email):
return None
email = str(email).strip().lower()
# 补全邮箱后缀
if '@' not in email:
return None
parts = email.split('@')
if not parts[0] or not parts[1]:
return None
# 确保有顶级域名
if '.' not in parts[1]:
return None
return email
cleaned_df['邮箱'] = cleaned_df['邮箱'].apply(clean_email)
# 2. 标准化电话
def clean_phone(phone):
if pd.isna(phone):
return None
phone = str(phone).strip()
# 只保留数字
phone = ''.join(filter(str.isdigit, phone))
if len(phone) == 11 and phone.startswith('1'):
return phone
return None
cleaned_df['电话'] = cleaned_df['电话'].apply(clean_phone)
# 3. 标准化年龄
def clean_age(age):
if pd.isna(age):
return None
age = str(age).strip()
# 移除"岁"等文字
age = age.replace('岁', '').strip()
try:
age_num = int(age)
if 0 < age_num < 150:
return age_num
except:
return None
return None
cleaned_df['年龄'] = cleaned_df['年龄'].apply(clean_age)
# 4. 标准化收入
def clean_income(income):
if pd.isna(income) or str(income).lower() == 'nan':
return None
income = str(income).strip()
# 移除¥、元等符号
income = income.replace('¥', '').replace('元', '').replace(',', '')
try:
income_num = float(income)
if income_num > 0:
return income_num
except:
return None
return None
cleaned_df['收入'] = cleaned_df['收入'].apply(clean_income)
# 5. 标准化状态
def clean_status(status):
if pd.isna(status):
return '未知'
status = str(status).strip().lower()
status_map = {
'active': '活跃', 'inactive': '不活跃', 'active!': '活跃',
'活跃': '活跃', '不活跃': '不活跃'
}
return status_map.get(status, '未知')
cleaned_df['状态'] = cleaned_df['状态'].apply(clean_status)
return cleaned_df
df_cleaned = comprehensive_clean(df)
print("\n清洗后的数据:")
print(df_cleaned)
print("\n清洗后数据类型:")
print(df_cleaned.dtypes)
# 保存清洗后的数据
df_cleaned.to_csv('cleaned_data.csv', index=False, encoding='utf-8-sig')
print("\n数据已保存到 'cleaned_data.csv'")
常用数据清洗技巧总结
import pandas as pd
# 1. 数据类型转换
def type_conversion_tips():
df = pd.DataFrame({'col1': ['1', '2', '3'], 'col2': ['2023-01-01', '2023-01-02', '2023-01-03']})
# 转换为数值
df['col1'] = pd.to_numeric(df['col1'], errors='coerce')
# 转换为日期
df['col2'] = pd.to_datetime(df['col2'])
return df
# 2. 处理重复值
def duplicate_handling(df):
# 检查重复
print(f"重复行数: {df.duplicated().sum()}")
# 删除重复
df_clean = df.drop_duplicates()
# 基于特定列删除重复
df_clean2 = df.drop_duplicates(subset=['列名1', '列名2'])
return df_clean
# 3. 数据标准化
def standardization_tips():
# 字符串标准化
df = pd.DataFrame({'text': [' Hello ', 'World ', ' Python ']})
df['text'] = df['text'].str.strip().str.lower() # 去除空格并转为小写
# 分类数据标准化
status_map = {'Y': '是', 'N': '否', 'yes': '是', 'no': '否'}
df['status'] = df['status'].map(status_map)
return df
# 4. 异常值处理
def outlier_handling(df, column, method='iqr'):
if method == 'iqr':
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 替换异常值
df[column] = df[column].clip(lower=lower_bound, upper=upper_bound)
return df
这些案例涵盖了大多数常见的数据清洗场景,根据实际需求,你可以组合使用这些技巧来处理更复杂的数据清洗任务。