
在数据分析实践中,我们经常会遇到以“宽格式”存储的时间序列数据,其中每个时间点(例如月份)对应一个独立的列。这种格式在展示时直观,但在进行跨时间维度(如季度、年度)的聚合计算时却显得笨拙。传统方法可能需要手动指定每个季度或年度包含的列名,这不仅效率低下,且难以适应动态的时间范围。本文将提供一种基于Pandas的通用解决方案,通过数据重塑和时间维度提取,实现对月度数据的自动化季度和年度汇总。
假设我们有一个Pandas DataFrame,其中包含多个实体(如产品A、B)在不同月份的数值数据。月份列的命名遵循YYYYMM格式。
示例数据:
import pandas as pd
data = {
'201003': [10, 14],
'201004': [11, 19],
'201005': [14, 20],
'201006': [22, 22],
'201007': [10, 26],
'201008': [19, 11],
'201101': [5, 8],
'201102': [7, 12],
'201103': [9, 15]
}
df_original = pd.DataFrame(data, index=['A', 'B'])
print("原始DataFrame:")
print(df_original)输出:
原始DataFrame: 201003 201004 201005 201006 201007 201008 201101 201102 201103 A 10 11 14 22 10 19 5 7 9 B 14 19 20 22 26 11 8 12 15
我们的目标是:
处理宽格式时间序列数据的关键一步是将其转换为“长格式”。Pandas的melt()函数是实现这一转换的强大工具。它将指定的列(这里是所有的月份列)“融化”成两列:一列包含原始列名(即YYYYMM),另一列包含对应的值。为了保留原始的行标识符('A'和'B'),我们需要先将其转换为一个常规列,再作为id_vars参数传递给melt()。
# 将索引转换为常规列,以便在melt操作中保留
df_melted = df_original.reset_index().rename(columns={'index': 'ID'})
# 使用melt函数将月份列转换为行
# id_vars: 不进行融化的列,这里是我们的实体ID
# var_name: 新的变量列的名称,将包含原始的YYYYMM列名
# value_name: 新的值列的名称,将包含原始的数值
df_long = df_melted.melt(id_vars='ID', var_name='YYYYMM', value_name='Value')
print("\n转换后的长格式DataFrame:")
print(df_long.head())输出:
转换后的长格式DataFrame: ID YYYYMM Value 0 A 201003 10 1 B 201003 14 2 A 201004 11 3 B 201004 19 4 A 201005 14
在长格式数据中,所有的月份信息都集中在YYYYMM列。我们可以利用字符串切片操作,从中提取出年份和月份。
# 从YYYYMM列中提取年份
df_long['Year'] = df_long['YYYYMM'].str[:4]
# 从YYYYMM列中提取月份
df_long['Month'] = df_long['YYYYMM'].str[4:]
print("\n提取年份和月份后的DataFrame:")
print(df_long.head())输出:
提取年份和月份后的DataFrame: ID YYYYMM Value Year Month 0 A 201003 10 2010 03 1 B 201003 14 2010 03 2 A 201004 11 2010 04 3 B 201004 19 2010 04 4 A 201005 14 2010 05
为了计算季度汇总,我们需要将月份映射到对应的季度。我们可以创建一个字典来定义这种映射关系,然后使用map()方法将其应用到Month列。
# 定义月份到季度的映射
month_quarter_map = {
'01': 1, '02': 1, '03': 1, # Q1
'04': 2, '05': 2, '06': 2, # Q2
'07': 3, '08': 3, '09': 3, # Q3
'10': 4, '11': 4, '12': 4 # Q4
}
# 应用映射创建Quarter列
df_long['Quarter'] = df_long['Month'].map(month_quarter_map)
print("\n添加季度信息后的DataFrame:")
print(df_long.head())输出:
添加季度信息后的DataFrame: ID YYYYMM Value Year Month Quarter 0 A 201003 10 2010 03 1 1 B 201003 14 2010 03 1 2 A 201004 11 2010 04 2 3 B 201004 19 2010 04 2 4 A 201005 14 2010 05 2
现在数据已经准备就绪,我们可以使用groupby()方法结合sum()进行汇总。
1. 季度汇总: 我们将按ID、Year和Quarter进行分组,然后对Value列求和。
df_quarterly_sums = df_long.groupby(['ID', 'Year', 'Quarter'])['Value'].sum().reset_index()
print("\n季度汇总结果:")
print(df_quarterly_sums)输出:
季度汇总结果: ID Year Quarter Value 0 A 2010 1 10 1 A 2010 2 47 2 A 2010 3 29 3 A 2011 1 21 4 B 2010 1 14 5 B 2010 2 61 6 B 2010 3 37 7 B 2011 1 35
如果希望将季度汇总结果转换为更接近原始宽格式的形态(例如,每个季度一个列),可以使用pivot_table或unstack:
df_quarterly_pivot = df_quarterly_sums.pivot_table(
index=['ID', 'Year'],
columns='Quarter',
values='Value',
fill_value=0 # 填充没有数据的季度为0
).add_prefix('Q').reset_index()
print("\n季度汇总结果(宽格式):")
print(df_quarterly_pivot)输出:
季度汇总结果(宽格式): ID Year Q1 Q2 Q3 0 A 2010 10 47 29 1 A 2011 21 0 0 2 B 2010 14 61 37 3 B 2011 35 0 0
2. 年度汇总: 我们将按ID和Year进行分组,然后对Value列求和。
df_annual_sums = df_long.groupby(['ID', 'Year'])['Value'].sum().reset_index()
print("\n年度汇总结果:")
print(df_annual_sums)输出:
年度汇总结果: ID Year Value 0 A 2010 86 1 A 2011 21 2 B 2010 112 3 B 2011 35
同样,年度汇总也可以转换为宽格式:
df_annual_pivot = df_annual_sums.pivot_table(
index='ID',
columns='Year',
values='Value',
fill_value=0
).add_prefix('Year_').reset_index()
print("\n年度汇总结果(宽格式):")
print(df_annual_pivot)输出:
年度汇总结果(宽格式): ID Year_2010 Year_2011 0 A 86 21 1 B 112 35
通过melt()、字符串操作和groupby()的组合使用,我们可以优雅且高效地将宽格式的月度数据汇总为季度和年度数据。这种方法避免了手动硬编码列名的繁琐,使得数据分析流程更加自动化和可扩展。掌握这种数据重塑和聚合技巧,对于处理时间序列数据的数据科学家和分析师来说至关重要。
以上就是Pandas数据框:高效汇总月度数据至季度与年度的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号