如何用更简洁优雅的方式在Pandas中按年度透视时间序列?
更简洁优雅的Pandas年度时间序列透视实现
当然有更清爽的实现方式!你的代码已经完成了需求,但Pandas的API设计里有更贴合其风格的方法,既能减少代码量,还能提升可读性和运行效率。
方法一:链式调用 + 透视(最推荐)
利用reset_index、assign和pivot的组合,一步完成转换,逻辑清晰且代码紧凑:
import pandas as pd import numpy as np # 生成模拟数据(和你的代码一致) daterange = pd.date_range(start='2000-01-01', end='2017-12-31', freq='10T') wind_speed = pd.Series(data=np.random.rand(daterange.size), index=daterange) # 核心转换代码 wind_speed_pivot = (wind_speed .reset_index(name='speed') # 将时间索引转为列,命名数值列为speed .assign( year=lambda x: x['index'].dt.year, # 提取年份 # 计算年内时间偏移量(索引减去当年1月1日) day_of_year=lambda x: x['index'] - pd.to_datetime(x['year'], format='%Y') ) .pivot(index='day_of_year', columns='year', values='speed') # 透视成目标格式 ) print(wind_speed_pivot)
方法二:GroupBy + Concat
如果你更习惯用分组的思路,也可以用列表推导式处理每个分组的索引,再一次性合并:
# 分组后处理每个组的索引,再横向合并 year_groups = wind_speed.groupby(wind_speed.index.year) wind_speed_pivot = pd.concat( [group.set_index(group.index - pd.Timestamp(f"{year}-01-01")) for year, group in year_groups], axis=1, # 横向合并为列 keys=year_groups.groups.keys() # 用年份作为列名 )
为什么这两种方法更好?
- 避免循环中的低效操作:你原来的循环里反复调用
join,每次都会生成新的DataFrame,数据量大时会有明显的性能损耗;而上面的方法都是一次性完成合并,效率更高。 - 代码更简洁可读:链式调用和列表推导式把逻辑浓缩在几行里,一眼就能看懂转换流程,维护起来更方便。
- 更贴合Pandas的设计哲学:利用内置的
pivot、concat等方法,而非手动循环处理,是Pandas推荐的操作方式。
这两种方法最终得到的结果和你原来的代码完全一致,但实现起来更优雅高效。
内容的提问来源于stack exchange,提问作者piiipmatz
相关产品推荐
相关产品推荐

