← 返回首页
📊

Pandas进阶:数据清洗、GroupBy、合并与透视表

📂 python ⏱ 3 min 588 words

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、数据合并和透视表等进阶技能,能让你处理更复杂的数据分析任务。关键原则:理解数据结构,选择合适的聚合方式,注意合并时的键匹配。