Pandas重采样时使用全局起止日期、指定缺失值填充为0及代码功能咨询
Pandas重采样时使用全局起止日期、指定缺失值填充为0及代码功能咨询
嗨,我来一步步帮你理清这些问题,让你彻底搞懂Pandas重采样的这些细节~
一、如何使用全局起止日期进行重采样
你现在是按series_col分组后单独重采样,每个组只会用自身的日期范围,但如果想让所有组统一使用整个数据集的最小/最大日期作为重采样的起止点,可以这样操作:
- 先计算全局的起止日期:
global_min_date = df['date'].min() global_max_date = df['date'].max()
- 在
resample时指定start和end参数,强制所有组都使用这个全局范围:
# 分组后按全局日期范围重采样 resampled_df = df.groupby('series_col').resample( 'W', on='date', label='left', loffset=pd.DateOffset(days=0), start=global_min_date, end=global_max_date )['value'].sum().reset_index()
这样不管每个组原本的日期范围如何,都会从全局最早日期到最晚日期生成完整的时间序列。
二、如何将重采样后的缺失值填充为0
你提到的场景:某个时间区间内没有数据,希望把对应的value设为0。这里要注意两个关键点:
- 默认情况下,
resample只会返回有数据的区间,缺失的区间根本不会出现在结果里,所以你看不到null值(那些行不存在)。 - 要生成完整的时间区间并填充0,需要在重采样后做两步:确保所有时间区间都被生成,再将空值替换为0。
具体实现可以这样:
# 先按全局日期范围重采样,保留所有区间 resampled_full = df.groupby('series_col').resample( 'W', on='date', label='left', loffset=pd.DateOffset(days=0), start=global_min_date, end=global_max_date )['value'].sum() # 将空值填充为0,再重置索引 resampled_final = resampled_full.fillna(0).reset_index()
这样像你例子中series_1在2023-02-13的周,就会显示value=0了。
另外,如果你想更直接,也可以用asfreq先生成完整时间序列,再填充0后求和,效果是一样的:
resampled_final = df.groupby('series_col').apply( lambda x: x.set_index('date').resample('W', label='left').asfreq().fillna(0)['value'].sum() ).reset_index()
三、解析你给出的代码功能
我们来逐段拆解这段代码到底在做什么:
df.groupby('series_col').resample('W', on='date', label='left', loffset=pd.DateOffset(days=0))['value'].sum().reset_index()
df.groupby('series_col'):把数据集按series_col列分组,每个组对应一个独立的时间序列。.resample('W', on='date', label='left', loffset=pd.DateOffset(days=0)):'W':按周进行重采样,默认每周日为周的结束点。on='date':指定用date列作为时间依据(而不是DataFrame的索引)。label='left':用每个时间区间的左端点作为该区间的标签(比如2023-02-06到2023-02-12的周,标签是2023-02-06)。loffset=pd.DateOffset(days=0):不对标签日期做偏移,保持左端点的原始日期。
['value'].sum():对每个组的每个时间区间内的value值求和,如果某个区间没有数据,求和结果会是NaN(但默认不会显示该行)。.reset_index():把重采样后的多级索引(series_col和日期标签)转换成普通列,让结果更易读。
为什么你没看到null值?因为默认情况下,resample只会保留有数据的区间,那些没有数据的区间不会出现在最终结果里,所以你看不到NaN。如果想要这些区间显示并填充0,就用我前面说的方法。
备注:内容来源于stack exchange,提问作者Tonino Fernandez
相关产品推荐
相关产品推荐

