Pandas进阶:数据清洗、GroupBy、合并与透视表
Pandas进阶:数据清洗、GroupBy、合并与透视表
掌握Pandas的基础操作后,本文将深入讲解数据清洗、分组聚合、数据合并和透视表等进阶技能,这些是实际数据分析工作中最常用的技术。
数据清洗
真实数据往往充满各种问题,数据清洗是分析前的关键步骤:
import pandas as pd
import numpy as np
# 模拟脏数据
df = pd.DataFrame({
'姓名': ['张三', ' 李四', '王五 ', None, '赵六'],
'年龄': [25, 30, -5, 35, 200],
'邮箱': ['zhang@qq.com', 'li@163.com', 'wang@gmail.com', 'zhao@126.com', 'invalid'],
'薪资': ['15000', '12000', '18000', '13000', '未知']
})
# 去除字符串空格
df['姓名'] = df['姓名'].str.strip()
# 处理异常值 - 年龄应在0-120之间
df.loc[df['年龄'] < 0, '年龄'] = np.nan
df.loc[df['年龄'] > 120, '年龄'] = np.nan
# 数据类型转换
df['薪资'] = pd.to_numeric(df['薪资'], errors='coerce')
# 正则提取邮箱域名
df['邮箱域名'] = df['邮箱'].str.extract(r'@(\w+)\.\w+')
# 删除重复行
df = df.drop_duplicates()
# 填充缺失值
df['年龄'] = df['年龄'].fillna(df['年龄'].median())
df['薪资'] = df['薪资'].fillna(df['薪资'].mean())
print(df)
数据替换与映射
import pandas as pd
df = pd.DataFrame({
'产品': ['A', 'B', 'A', 'C', 'B', 'A'],
'等级': ['高', '低', '中', '高', '低', '中']
})
# 简单替换
df['等级_num'] = df['等级'].replace({'低': 1, '中': 2, '高': 3})
# 使用map进行映射
product_map = {'A': '电子产品', 'B': '服装', 'C': '食品'}
df['产品类别'] = df['产品'].map(product_map)
# apply函数处理
df['薪资等级'] = df['等级'].apply(lambda x: '高薪' if x == '高' else '普通')
print(df)
GroupBy分组聚合
GroupBy是Pandas最强大的功能之一,实现"拆分-应用-合并"的分析模式:
import pandas as pd
# 销售数据
sales = pd.DataFrame({
'区域': ['华东', '华东', '华北', '华北', '华东', '华北'],
'产品': ['手机', '电脑', '手机', '电脑', '手机', '电脑'],
'销量': [100, 50, 80, 60, 120, 40],
'单价': [3000, 8000, 3000, 8000, 3000, 8000]
})
sales['销售额'] = sales['销量'] * sales['单价']
# 基础分组聚合
region_total = sales.groupby('区域')['销售额'].sum()
print("各区域总销售额:")
print(region_total)
# 多列分组
grouped = sales.groupby(['区域', '产品']).agg({
'销量': 'sum',
'销售额': ['sum', 'mean']
})
print("\n分组统计:")
print(grouped)
# 自定义聚合函数
def sales_range(x):
return x.max() - x.min()
result = sales.groupby('区域')['销量'].agg(['sum', 'mean', sales_range])
print(result)
# 过滤分组
large_groups = sales.groupby('区域').filter(lambda x: x['销量'].sum() > 200)
print("\n销量超过200的区域数据:")
print(large_groups)
Transform与Apply
import pandas as pd
df = pd.DataFrame({
'部门': ['技术', '技术', '销售', '销售', '技术'],
'姓名': ['张三', '李四', '王五', '赵六', '钱七'],
'薪资': [15000, 18000, 12000, 13000, 16000]
})
# Transform - 保持原数据行数的分组计算
df['部门平均薪资'] = df.groupby('部门')['薪资'].transform('mean')
df['薪资vs部门均值'] = df['薪资'] - df['部门平均薪资']
print(df)
# Apply - 可改变数据形状
def top_n_by_salary(group, n=1):
return group.nlargest(n, '薪资')
top_performers = df.groupby('部门').apply(top_n_by_salary, n=1)
print("\n各部门薪资最高员工:")
print(top_performers)
数据合并
Pandas提供类似SQL的多种数据合并方式:
import pandas as pd
# 员工信息
employees = pd.DataFrame({
'员工ID': [1, 2, 3, 4],
'姓名': ['张三', '李四', '王五', '赵六'],
'部门ID': [101, 102, 101, 103]
})
# 部门信息
departments = pd.DataFrame({
'部门ID': [101, 102, 103],
'部门名称': ['技术部', '销售部', '市场部']
})
# 业绩数据
performance = pd.DataFrame({
'员工ID': [1, 2, 3],
'Q1业绩': [100, 120, 90],
'Q2业绩': [110, 130, 95]
})
# 内连接
inner = pd.merge(employees, departments, on='部门ID')
print("内连接:\n", inner)
# 左连接
left = pd.merge(employees, departments, on='部门ID', how='left')
print("\n左连接:\n", left)
# 多表合并
full = pd.merge(
pd.merge(employees, departments, on='部门ID'),
performance,
on='员工ID',
how='left'
)
print("\n完整信息:\n", full)
# 连接索引
df1 = pd.DataFrame({'A': [1, 2]}, index=['a', 'b'])
df2 = pd.DataFrame({'B': [3, 4]}, index=['a', 'b'])
result = pd.concat([df1, df2], axis=1)
print("\n按索引连接:\n", result)
透视表
透视表是数据汇总分析的强大工具:
import pandas as pd
# 销售明细数据
sales = pd.DataFrame({
'月份': ['1月', '1月', '2月', '2月', '3月', '3月'] * 2,
'产品': ['手机'] * 6 + ['电脑'] * 6,
'区域': ['华东', '华北'] * 6,
'销量': [100, 80, 110, 85, 120, 90, 50, 40, 55, 45, 60, 50]
})
# 创建透视表
pivot = pd.pivot_table(
sales,
values='销量',
index='月份',
columns='产品',
aggfunc='sum',
margins=True, # 添加汇总行/列
margins_name='总计'
)
print("产品月度销量透视表:")
print(pivot)
# 多值透视表
pivot2 = pd.pivot_table(
sales,
values='销量',
index=['区域', '月份'],
columns='产品',
aggfunc=['sum', 'mean']
)
print("\n多维度透视表:")
print(pivot2)
# 交叉表
cross = pd.crosstab(
sales['区域'],
sales['产品'],
values=sales['销量'],
aggfunc='sum',
margins=True
)
print("\n交叉表:")
print(cross)
数据重塑
import pandas as pd
# 宽格式数据
wide = pd.DataFrame({
'姓名': ['张三', '李四', '王五'],
'Q1': [100, 120, 90],
'Q2': [110, 130, 95],
'Q3': [105, 125, 100]
})
# 宽转长(melt)
long = pd.melt(wide, id_vars=['姓名'], var_name='季度', value_name='业绩')
print("长格式:")
print(long)
# 长转宽(pivot)
back_wide = long.pivot(index='姓名', columns='季度', values='业绩')
print("\n宽格式:")
print(back_wide)
实战:综合分析
import pandas as pd
# 创建复杂数据集
orders = pd.DataFrame({
'订单ID': range(1, 11),
'客户': ['A', 'B', 'A', 'C', 'B', 'A', 'C', 'A', 'B', 'C'],
'产品类别': ['电子', '服装', '电子', '食品', '服装', '电子', '食品', '服装', '电子', '食品'],
'金额': [3000, 200, 5000, 100, 300, 2500, 150, 400, 4000, 120],
'日期': pd.date_range('2024-01-01', periods=10)
})
# 客户消费分析
customer_analysis = orders.groupby('客户').agg(
总消费=('金额', 'sum'),
订单数=('订单ID', 'count'),
平均订单金额=('金额', 'mean'),
消费品类数=('产品类别', 'nunique')
)
# 找出高价值客户
high_value = customer_analysis[customer_analysis['总消费'] > 3000]
print("高价值客户:")
print(high_value)
# 产品类别分析
category = orders.groupby('产品类别')['金额'].agg(['sum', 'count', 'mean'])
print("\n产品类别分析:")
print(category)
总结
掌握GroupBy、数据合并和透视表等进阶技能,能让你处理更复杂的数据分析任务。关键原则:理解数据结构,选择合适的聚合方式,注意合并时的键匹配。