如何用Pandas正确聚合时间序列为DataFrame而非Series
问题根因
你执行重采样后得到Series,是因为lambda函数中操作的df.amount本身是单列Series结构,重采样、求和操作不会改变数据结构,groupby.apply对每组返回Series时,最终结果就是双层MultiIndex的Series:第一层索引为user,第二层为周粒度的timestamp,值为对应捐赠总额。
解决方法
方案1:直接将现有Series转为符合要求的DataFrame
对得到的agg_donations执行索引转列+重命名操作即可:
# 把双层索引转为普通列 agg_donations_df = agg_donations.reset_index() # 重命名列和邮件表的字段对齐,方便后续合并 agg_donations_df.columns = ['member', 'week', 'amount'] # 保证两个表的week字段格式一致,避免合并不上 all_email['week'] = pd.to_datetime(all_email['week'])
方案2:修改重采样代码,直接生成DataFrame
把lambda函数里的df.amount改为df[['amount']],用两层方括号取列会返回DataFrame结构,后续处理后直接得到你要的格式:
donations.timestamp = pd.to_datetime(donations.timestamp) donations.set_index('timestamp', inplace = True) # 这里把df.amount改成df[['amount']] agg_donations = donations.groupby('user').apply(lambda df: df[['amount']].resample("W-MON").sum().dropna()).reset_index() agg_donations.columns = ['member', 'week', 'amount']
更简洁的合并逻辑
你原代码里的循环合并效率低还容易出错,可以直接用merge一次性完成关联:
merged_df = pd.merge( all_email, agg_donations_df, on=['member', 'week'], how='left' # 没有捐赠的周填充金额为0 ).fillna({'amount': 0}) # 按需保留字段,注意EmailsOpened的大小写要和你实际字段名一致 merged_df = merged_df[['member', 'week', 'EmailsOpened', 'amount']]
内容的提问来源于stack exchange,提问作者Johnny Bigoode
相关产品推荐
相关产品推荐

