在掌握了 Pandas 的基础操作后,我们往往会面临更复杂的业务场景。现实世界中的数据很少是孤立存在的,它们通常分散在不同的表格中,并且带有时间戳。今天,我们就来解锁 Pandas 的两大进阶武器:多表合并与时间序列分析,让你的数据处理能力再上一个台阶。

一、 多表合并:像 SQL 一样优雅地关联数据

在数据分析中,将来自不同来源的数据整合在一起是家常便饭。Pandas 提供了多种合并方式,其中最核心的是 mergeconcat

1. 核心利器:merge() 函数

merge 函数的逻辑与 SQL 中的 JOIN 操作非常相似。它通过一个或多个“键(Key)”将两张表关联起来。

# 创建两张示例表
df_users = pd.DataFrame({'user_id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df_orders = pd.DataFrame({'order_id': [101, 102, 103], 'user_id': [1, 2, 4], 'amount': [100, 200, 300]})

# 左连接:保留左表(用户表)的所有记录,右表无匹配则填充 NaN
result = pd.merge(df_users, df_orders, on='user_id', how='left')

2. 进阶技巧:使用 reduce 批量合并多表

当需要合并三张甚至更多的表时,新手往往会写一堆 for 循环反复调用 merge。这种做法不仅代码冗长,而且在遇到列名冲突时极易报错。最佳实践是使用 functools.reduce 将合并逻辑封装起来:

from functools import reduce

# 定义一个标准的左连接函数
def left_merge(left, right):
    return pd.merge(left, right, on='user_id', how='left')

# 将所有需要合并的表放入列表,主表放在最前面
dfs = [df_users, df_orders, df_logs]

# 使用 reduce 优雅地完成多表合并
final_result = reduce(left_merge, dfs)

3. 避坑指南:合并前的数据清洗

在执行合并前,务必检查参与合并的“键”的数据类型是否一致(例如不能一个是 int,另一个是 str)。同时,建议提前对右表进行去重(drop_duplicates),否则合并时可能会产生笛卡尔积,导致数据量呈指数级膨胀。

二、 时间序列分析:挖掘数据背后的时间规律

金融数据、物联网传感器数据、用户行为日志等都带有时间属性。Pandas 内置了极其强大的时间序列处理工具。

1. 统一时间格式并设置索引

处理时间数据的第一步,永远是将其转换为 Pandas 的 datetime 类型,并将其设置为 DataFrame 的索引(Index)。这是后续所有高级操作的基础。

# 将字符串转换为时间对象,errors='coerce' 会将非法格式转为 NaT
df['event_time'] = pd.to_datetime(df['event_time'], errors='coerce')

# 将时间列设为索引
df.set_index('event_time', inplace=True)

2. 重采样 (Resample):时间粒度的转换器

重采样允许我们在不同的时间频率之间转换数据。例如,将高频的分钟级数据降采样为日级数据,或者将日级数据升采样。

# 降采样:计算每天的总销售额
daily_sales = df.resample('D')['amount'].sum()

# 升采样并插值:将日频数据转换为小时频,并用线性插值填充缺失值
hourly_sales = df.resample('H').interpolate(method='linear')

3. 移动窗口 (Rolling):捕捉局部动态趋势

在分析股票或传感器数据时,我们通常需要计算移动平均线或移动标准差来平滑噪声、识别异常。

# 计算 7 天移动平均线,min_periods=3 表示窗口内至少有3个有效值才计算
df['ma_7'] = df['amount'].rolling(window=7, min_periods=3).mean()

# 计算 30 天指数加权移动平均 (EWMA),给予近期数据更高的权重
df['ewma_30'] = df['amount'].ewm(span=30).mean()

三、 实战演练:多表合并与时间序列的联动

让我们把这两大进阶技巧结合起来,解决一个真实的业务需求:分析各渠道最近 3 个月的日均转化率趋势

# 1. 使用 reduce 合并用户行为表、订单表和渠道信息表
dfs = [user_behavior, orders, channel_info]
merged_df = reduce(lambda l, r: pd.merge(l, r, on='user_id', how='left'), dfs)

# 2. 转换时间并设置索引
merged_df['event_time'] = pd.to_datetime(merged_df['event_time'])
merged_df.set_index('event_time', inplace=True)

# 3. 使用 Grouper 按自然月和渠道进行动态分组,计算均值
monthly_trend = merged_df.groupby([
    pd.Grouper(freq='M'),  # 按自然月对齐
    'channel'
])['conversion_rate'].mean()

print(monthly_trend)

进阶学习建议

Pandas 的进阶内容非常庞大,除了多表合并和时间序列,还有透视表(pivot_table)、复杂的自定义 apply 函数等。建议大家在实战中遇到具体问题时,带着目的去查阅官方文档。

更多推荐