在数据分析工作中,时间序列数据的年度统计是高频需求,使用Pandas可以快速完成时间序列数据的年度平均值计算,无需复杂的循环逻辑,大幅提升处理效率。

核心前置准备
首先需要将数据的时间列转换为Pandas的DatetimeIndex类型,这是后续所有时间相关计算的基础。如果原始数据的时间列是字符串格式,需要先做转换。
import pandas as pd
import numpy as np
# 构造示例时间序列数据,时间跨度为2021-2023年,每天一条记录
date_rng = pd.date_range(start='2021-01-01', end='2023-12-31', freq='D')
data = pd.DataFrame(date_rng, columns=['date'])
data['value'] = np.random.randint(10, 100, size=len(date_rng))
# 将date列设置为时间索引
data.set_index('date', inplace=True)
print(data.head())
方法一:使用resample函数计算
resample是Pandas专门为时间序列重采样设计的方法,按年度重采样后直接调用mean方法即可得到年度平均值,是最直观的实现方式。
# 按年度重采样计算平均值,'Y'表示按年聚合,也可以用'A'
yearly_avg_resample = data.resample('Y').mean()
# 重置索引,将时间列从索引转为普通列,方便后续处理
yearly_avg_resample = yearly_avg_resample.reset_index()
# 格式化时间列,只保留年份
yearly_avg_resample['date'] = yearly_avg_resample['date'].dt.year
print(yearly_avg_resample)
方法二:使用groupby结合Grouper计算
如果数据的时间列是普通列而非索引,或者需要同时按照其他维度分组,可以使用groupby配合Grouper对象实现年度平均值计算。
# 先重置索引,让date回到普通列 data_reset = data.reset_index() # 使用Grouper指定时间列和聚合频率,按年分组计算平均值 yearly_avg_groupby = data_reset.groupby(pd.Grouper(key='date', freq='Y'))['value'].mean().reset_index() yearly_avg_groupby['date'] = yearly_avg_groupby['date'].dt.year print(yearly_avg_groupby)
方法三:提取年份后直接groupby
如果不需要严格按自然年对齐,也可以直接从时间列提取年份,再按年份分组计算平均值,这种方式逻辑更简单,适合对时间边界要求不高的场景。
# 提取年份列
data_reset['year'] = data_reset['date'].dt.year
# 按年份分组计算平均值
yearly_avg_extract = data_reset.groupby('year')['value'].mean().reset_index()
print(yearly_avg_extract)
不同方法对比
三种方法的适用场景和特点如下:
| 方法 | 适用场景 | 优势 | 注意事项 |
|---|---|---|---|
| resample | 时间列为索引,仅需时间维度聚合 | 语法简洁,专为时间序列设计,执行效率高 | 要求数据的时间列已经是索引 |
| groupby+Grouper | 时间列为普通列,或需要多维度分组 | 灵活性高,支持同时按其他字段分组 | 需要显式指定时间列名 |
| 提取年份后groupby | 对时间边界要求低,逻辑简单优先 | 逻辑直观,无需理解时间频率参数 | 不会自动对齐自然年边界,仅按年份数值分组 |
注意事项
- 如果数据中存在缺失值,mean方法默认会忽略NaN,若需要保留缺失值标记,可以提前用
fillna方法处理。 - resample的freq参数中,'Y'和'A'都表示按年聚合,默认是自然年结束,若需要按财年计算,可以调整freq参数或者先对时间做偏移处理。
- 当数据量较大时,优先选择resample方法,其底层做了针对性优化,比普通groupby的效率更高。
完整示例整合
import pandas as pd
import numpy as np
# 1. 构造数据
date_rng = pd.date_range(start='2021-01-01', end='2023-12-31', freq='D')
df = pd.DataFrame(date_rng, columns=['date'])
df['value'] = np.random.randint(10, 100, size=len(date_rng))
# 2. 设置时间索引
df.set_index('date', inplace=True)
# 3. 计算年度平均值
yearly_avg = df.resample('Y').mean().reset_index()
yearly_avg['date'] = yearly_avg['date'].dt.year
yearly_avg.columns = ['year', 'avg_value']
print("年度平均值结果:")
print(yearly_avg)