优化DatetimeIndex嵌套循环:高效转换多国家时序DataFrame
高效实现DataFrame格式转换(替代嵌套循环)
你的需求是把含小时级数据的宽表转换成MultiIndex列(国家代码+年份)、索引为一年中小时位置(0-8759)的格式,用来绘制年度箱线图。原来的嵌套循环因为逐列逐行赋值,效率很低,我们可以利用pandas的矢量化操作和内置函数大幅提升速度。
优化方案代码
# 直接用groupby+apply+concat实现批量转换 ds = pd.concat( [ col.groupby(df.index.year).apply(lambda x: x.reset_index(drop=True)) for _, col in df.items() ], axis=1, keys=df.columns ) # 如果需要强制统一为8760行(处理闰年多出来的24小时),可以修改apply部分: # ds = pd.concat( # [ # col.groupby(df.index.year).apply(lambda x: x.reset_index(drop=True).iloc[:8760]) # for _, col in df.items() # ], # axis=1, # keys=df.columns # )
方案解释
- 分组处理单个国家的数据:对每个国家的列(
col),按年份分组(groupby(df.index.year)),然后用apply(lambda x: x.reset_index(drop=True))把每组的小时数据重置索引为0-8759(或闰年的0-8783),这样每个年份对应一个长度一致的Series。 - 批量拼接结果:用
pd.concat把所有国家的处理结果按列拼接,keys=df.columns参数会自动把国家代码作为MultiIndex的上层,年份作为下层,正好得到你需要的列结构。
为什么比原代码快?
原代码的嵌套循环中,每次ds.loc[:, (reg, year)] = ...都会修改整个DataFrame,触发多次内存复制,当数据量较大(28个国家×30年)时,效率会急剧下降。而优化方案利用pandas的批量处理逻辑,所有操作都是在底层矢量化执行,避免了逐元素赋值的开销,速度能提升数倍甚至数十倍。
验证效果
转换完成后,你可以直接用ds[('CN', 2020)].plot(kind='box')这样的代码绘制单个国家某一年的箱线图,和原代码的输出效果完全一致,但执行效率大幅提升。
内容的提问来源于stack exchange,提问作者stack4science
相关产品推荐
相关产品推荐

