Pandas Period列转换频率遇NaT问题:为何设为索引才正常?
Pandas Period列转年度周期:直接调用asfreq返回NaT的原因及解决办法
问题场景
处理Pandas Period类型数据时,将日期列转成月度周期(to_period('M'))后,想要转成年度周期:
- 直接对Series调用
asfreq('Y'),结果全是NaT - 将该列设为索引后再调用
asfreq('Y')却能正常工作
示例代码:
import pandas as pd from datetime import datetime data = pd.DataFrame({ 'status' : ['pending', 'pending','pending', 'canceled','canceled','canceled', 'confirmed', 'confirmed','confirmed'], 'product' : ['afiliates', 'pre-paid', 'giftcard','afiliates', 'pre-paid', 'giftcard','afiliates', 'pre-paid', 'giftcard'], 'brand' : ['brand_1', 'brand_2', 'brand_3','brand_1', 'brand_2', 'brand_3','brand_1', 'brand_2', 'brand_3'], 'date' : [datetime(2022,1,1),datetime(2023,6,1),datetime(2020,1,12),datetime(2025,1,1),datetime(2024,1,1),datetime(2023,1,1),datetime(2021,1,1),datetime(2022,1,1),datetime(2022,1,1)], 'gmv' : [100,100,100,100,100,100,100,100,100]}) # 设置月度周期列 data['month'] = data.date.dt.to_period('M') # 直接调用asfreq得到NaT data['year'] = data.month.asfreq('Y') # 设为索引后asfreq正常工作 data['year'] = data['month'] data = data.set_index('year') data = data.asfreq('Y')
原因分析
核心差异在于普通Series的asfreq()方法和基于PeriodIndex的asfreq()逻辑完全不同:
- 普通Series调用
asfreq()时,它的设计是针对带时间索引的序列进行重采样/频率转换,而非对Series内部的Period值做类型转换。因为month列是普通数据列而非索引,asfreq('Y')无法识别如何将单个月度Period转成年度,直接返回NaT。 - 当把Period列设为索引后,DataFrame的
asfreq('Y')是基于PeriodIndex操作的,此时会正确将每个月度Period映射到对应的年度Period(比如2023-06→2023)。
正确解决方案
不需要绕到索引,直接对Period列用以下两种方法就能完成转换:
方法1:用dt.to_period('Y')
data['year'] = data['month'].dt.to_period('Y')
方法2:用astype('period[Y]')
data['year'] = data['month'].astype('period[Y]')
验证结果
执行后data['year']会正确显示每个月度对应的年度周期,不会出现NaT。
内容的提问来源于stack exchange,提问作者FábioRB
相关产品推荐
相关产品推荐

