引言

某电商公司的运营团队拿到一份“双11订单数据”,包含10万条记录,却因数据混乱无法直接分析:

  • 订单时间列混合了2023-11-11 08:3011/11 20:00两种格式;
  • 用户年龄列存在NaN(缺失值)和-5(异常值);
  • 需要合并“订单表”和“用户信息表”,但两表的用户ID命名不同(user_id vs uid);
  • 想按“地区+商品品类”分组,统计每小时的销售额和客单价。

这些问题的解决方案,都藏在Pandas的高级操作中——它不仅是“数据处理工具”,更是“数据分析的瑞士军刀”。本文将通过这份“双11订单数据”的完整分析案例,带你掌握Pandas数据清洗、合并、分组聚合的核心技巧,从“数据整理”到“业务洞察”一步到位。


一、数据清洗:让混乱数据“焕然一新”

数据清洗是数据分析的第一步,Pandas提供了针对缺失值、重复值、异常值的全套解决方案。

1.1 缺失值处理:识别→分析→修复

1.1.1 缺失值识别

使用isnull()info()快速定位缺失列:

import pandas as pd
import numpy as np

# 读取示例数据(假设订单数据)
df = pd.read_csv("double11_orders.csv")
print(df.isnull().sum())  # 统计每列缺失值数量
# 输出:
# user_age       120
# product_brand    30
# ...
1.1.2 缺失值分析
  • 机制判断:缺失是随机的(如用户未填写年龄),还是系统性的(如某品牌数据未同步)?
  • 处理策略:删除(缺失比例>70%)、填充(业务逻辑或统计值)、保留(缺失本身是信息)。
1.1.3 缺失值修复示例
# 策略1:删除缺失严重的列(如product_brand缺失30条,但总数据10万,可保留)
# df.drop(columns=['product_brand'], inplace=True)  # 谨慎使用!

# 策略2:填充用户年龄(用中位数,避免均值受异常值影响)
age_median = df['user_age'].median()  # 计算中位数(如28)
df['user_age'].fillna(age_median, inplace=True)  # 填充缺失值

# 策略3:分类填充(如商品品牌缺失时标记为"未知")
df['product_brand'] = df['product_brand'].fillna("未知品牌")

1.2 重复值处理:去重保真实

1.2.1 识别重复行

duplicated()返回布尔Series,标记是否为重复行(默认保留第一条):

duplicate_mask = df.duplicated(subset=['order_id'])  # 按订单ID判断重复
print(f"重复行数:{duplicate_mask.sum()}")  # 输出:5(假设有5条重复订单)
1.2.2 删除重复行
df_clean = df.drop_duplicates(subset=['order_id'], keep='first')  # 保留第一条

1.3 异常值处理:用统计方法揪出“离群点”

异常值(如年龄为-5或200)会严重影响分析结果,常用方法:

  • IQR法(适用于偏态分布):计算四分位数范围(Q3-Q1),定义[Q1-1.5IQR, Q3+1.5IQR]外的值为异常;
  • Z-score法(适用于正态分布):计算标准差倍数(如|Z|>3视为异常)。
示例:用IQR法处理用户年龄异常值
def remove_outliers_iqr(df, column):
    q1 = df[column].quantile(0.25)
    q3 = df[column].quantile(0.75)
    iqr = q3 - q1
    lower = q1 - 1.5 * iqr
    upper = q3 + 1.5 * iqr
    # 标记异常值并替换为中位数(或删除)
    df[column] = np.where((df[column] < lower) | (df[column] > upper), 
                          df[column].median(), 
                          df[column])
    return df

df_clean = remove_outliers_iqr(df_clean, 'user_age')

二、数据合并:多表关联的“万能钥匙”

实际分析中,数据常分散在多张表中(如订单表+用户表+商品表),Pandas提供了concat(纵向拼接)、merge(横向关联)、join(基于索引的关联)三种合并方式。

2.1 concat:纵向拼接(行合并)

适用于结构相同的表合并(如分月的订单数据):

# 假设10月和11月订单表结构相同
oct_orders = pd.read_csv("oct_orders.csv")
nov_orders = pd.read_csv("nov_orders.csv")
all_orders = pd.concat([oct_orders, nov_orders], ignore_index=True)  # 重置索引

2.2 merge:横向关联(列合并)

适用于按关键字段关联不同表(如订单表+用户表按user_id关联):

# 用户信息表(假设)
users = pd.read_csv("users.csv")  # 包含user_id, user_city(用户所在城市)

# 合并订单表与用户表(按user_id关联,保留所有订单)
orders_with_users = pd.merge(
    left=df_clean,          # 左表(订单表)
    right=users,            # 右表(用户表)
    left_on='user_id',      # 左表关联键
    right_on='uid',         # 右表关联键(注意命名不同)
    how='left',             # 左连接(保留所有订单)
    suffixes=('_order', '_user')  # 列名冲突时的后缀
)

2.3 join:基于索引的快速关联

若表已设置索引(如用户表以uid为索引),joinmerge更高效:

users.set_index('uid', inplace=True)  # 设置用户表索引为uid
orders_with_users = df_clean.set_index('user_id').join(users, how='left')  # 按索引关联

三、数据分组与聚合:从“数据堆”到“业务洞察”

分组(groupby)和聚合(agg)是Pandas的核心分析功能,能将原始数据转化为可决策的统计指标(如各地区销售额、各品类客单价)。

3.1 基础分组:单维度统计

按“商品品类”分组,统计销售额和订单量:

category_stats = df_clean.groupby('product_category').agg({
    'order_amount': 'sum',    # 销售额总和
    'order_id': 'count',      # 订单量(去重后)
    'user_age': 'mean'        # 用户年龄均值
}).rename(columns={
    'order_amount': '总销售额',
    'order_id': '总订单量',
    'user_age': '平均年龄'
})

3.2 高级分组:多维度与多级索引

按“地区+商品品类”分组(二维分组),并按销售额降序排序:

# 先添加“地区”列(从用户城市中提取,如“北京”→“华北”)
region_map = {
    '北京': '华北', '天津': '华北', '上海': '华东', '杭州': '华东', ...
}
df_clean['region'] = df_clean['user_city'].map(region_map)

# 多维度分组(地区+品类)
region_category_stats = df_clean.groupby(['region', 'product_category']).agg({
    'order_amount': ['sum', 'mean'],  # 总销售额、平均销售额
    'user_id': 'nunique'              # 独立用户数(去重)
})

# 多级索引展平(方便导出)
region_category_stats.columns = ['_'.join(col).strip() for col in region_category_stats.columns]
region_category_stats.reset_index(inplace=True)  # 索引转列

3.3 分组后过滤:filtertransform

3.3.1 filter:筛选满足条件的组

筛选“总销售额>100万”的地区:

high_sales_regions = df_clean.groupby('region').filter(
    lambda x: x['order_amount'].sum() > 1_000_000
)
3.3.2 transform:组内标准化(如计算各订单的销售额占品类的比例)
# 添加“品类销售额占比”列
df_clean['category_amount_pct'] = df_clean.groupby('product_category')['order_amount'].transform(
    lambda x: x / x.sum()
)

3.4 实战案例:双11各时段销售趋势分析

需求:统计“各地区+各小时”的销售额,输出类似以下格式:

region hour total_sales
华北 8 123456.00
华北 9 156789.00
步骤1:时间列格式化(字符串转datetime)
# 原始时间列可能为"2023-11-11 08:30:15"或"11/11 20:00",统一转换
df_clean['order_time'] = pd.to_datetime(df_clean['order_time'], 
                                        format="%Y-%m-%d %H:%M:%S", 
                                        errors='coerce')  # 错误转换为NaT
df_clean['hour'] = df_clean['order_time'].dt.hour  # 提取小时
步骤2:分组聚合
hourly_sales = df_clean.groupby(['region', 'hour']).agg(
    total_sales=('order_amount', 'sum')
).reset_index()
步骤3:可视化(结合Matplotlib)
import matplotlib.pyplot as plt

plt.figure(figsize=(12, 6))
for region in hourly_sales['region'].unique():
    data = hourly_sales[hourly_sales['region'] == region]
    plt.plot(data['hour'], data['total_sales'], label=region, marker='o')

plt.title('双11各地区每小时销售额趋势')
plt.xlabel('小时(0-23)')
plt.ylabel('总销售额(元)')
plt.xticks(range(24))
plt.legend()
plt.grid(True)
plt.show()

四、常见问题与最佳实践

问题1:groupby后索引混乱,无法直接导出

解决方案:使用reset_index()将多级索引转为普通列:

grouped = df.groupby(['a', 'b']).sum()
grouped = grouped.reset_index()  # 索引转列,得到普通DataFrame

问题2:合并数据时出现重复列(如两表都有user_age

解决方案:通过suffixes参数指定后缀,或提前重命名列:

pd.merge(df1, df2, on='id', suffixes=('_df1', '_df2'))  # 自动添加后缀

问题3:处理大文件时内存不足

解决方案

  • 分块读取(pd.read_csv(chunksize=10000));
  • 仅读取需要的列(usecols=['col1', 'col2']);
  • 使用category类型优化内存(适用于重复值多的列,如product_category):
    df['product_category'] = df['product_category'].astype('category')
    

最佳实践:

  1. 先清洗后分析:数据清洗的时间占比应≥60%(避免“垃圾进,垃圾出”);
  2. 用向量化操作替代循环:Pandas的apply效率低,优先使用strdt等内置向量化方法;
  3. 保留中间结果:关键步骤保存为CSV(to_csv),避免重复计算;
  4. 善用文档与社区:Pandas官方文档(https://pandas.pydata.org/docs/)和Stack Overflow是解决问题的“利器”。

五、总结与学习路径

Pandas的高级应用是数据分析从“能用”到“高效”的关键:

  • 数据清洗解决数据质量问题(缺失、重复、异常);
  • 数据合并整合多源数据(纵向拼接、横向关联);
  • 分组聚合从数据中提取业务洞察(多维统计、趋势分析)。

学习建议

  1. 从真实业务数据入手(如Kaggle的电商数据集);
  2. 练习复杂查询(如“各品类月销售额环比增长”);
  3. 结合NumPy(数值计算)和Matplotlib/Seaborn(可视化)形成完整分析链路。

掌握这些技巧后,你将能轻松处理百万级数据,从“数据处理员”升级为“业务分析师”——下一次面对混乱数据时,Pandas就是你的“降维打击”武器!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐