Pandas按日期区间的日度成交量重采样为月度数据的高效方案
疑问1:是否有更高效的实现方式?
现有方案需要把日期区间拆成单日再聚合,核心问题是做了很多无效计算,你要的是月度结果,完全不需要拆到单日维度,直接按覆盖的月份拆分即可,内存开销能降低几十上百倍。
实现代码如下:
import pandas as pd # 先把起止日期转为datetime格式 df[["start", "end"]] = df[["start", "end"]].apply(pd.to_datetime) # 为每一行生成它覆盖的所有月份首日 df["month"] = df.apply(lambda x: pd.date_range(x["start"], x["end"], freq="MS"), axis=1) # 拆分行,一行对应一个覆盖的月份 df = df.explode("month", ignore_index=True) # 按月份+地点聚合求和,直接转为宽表格式 result = df.groupby(["month", "loc"])["volume"].sum().unstack("loc")
运行后得到的result和你预期的输出完全一致,且不需要处理单日量级的数据,效率提升非常明显。
疑问2:MultiIndex下resample报错的原因及无reset_index实现方法
报错原因
你执行groupby(by=['GroupDate','loc']).sum()后得到的是双层MultiIndex结构,第一层索引是GroupDate(时间类型),第二层索引是loc(地点字符串)。而resample默认要求待操作的对象索引是单一的时间类索引(DatetimeIndex/PeriodIndex等),它无法自动识别MultiIndex里哪一层是时间维度,所以直接调用会抛出类型错误。
不需要reset_index的实现方法
你可以直接指定resample作用的索引层级,或者先把loc维度转到列再做重采样,两种写法都不需要调用reset_index:
写法1:先把loc转到列维度再重采样
df = df.groupby(by=['GroupDate','loc'])['volume'].sum() # unstack把loc从索引层转到列,此时索引只剩GroupDate,符合resample的要求 result = df.unstack('loc').resample('MS').mean()
写法2:用level参数指定resample作用的索引层
df = df.groupby(by=['GroupDate','loc'])['volume'].sum() # 指定resample作用在第0层索引(也就是GroupDate层) result = df.resample('MS', level=0).mean().unstack('loc')
内容的提问来源于stack exchange,提问作者thesimplevoodoo
相关产品推荐
相关产品推荐

