如何在Pandas中按日期遍历数组并汇总金额(含其他国家求和)
最优方案:基于固定Top N国家+OTHERS计算多日期金额汇总
问题背景
现有大型Pandas DataFrame,核心列包括Countries(交易发生国)、Amount(浮点型金额),索引为时间戳timestamp。已基于今日数据生成Top N国家及"OTHERS"的金额汇总表,现在需要为这个新表添加历史日期列,按今日确定的Top N国家和"OTHERS"分组,计算对应历史日期的金额总和,目标格式如下:
| Country | 22 July 2022 | 21 July 2022 | 20 July 2022 | ... |
|---|---|---|---|---|
| GERMANY | 44779917.87 | SUM here | SUM here | ... |
| RUSSIA | 39270673.77 | SUM here | SUM here | ... |
| ISRAEL | 1436654.17 | SUM here | SUM here | ... |
| UKRAINE | 1080417.21 | ... | ... | ... |
| KAZAKSHTAN | 1046430.92 | ... | ... | ... |
| MOLDOVA | 250959.07 | ... | ... | ... |
| ARMENIA | 109161.46 | ... | ... | ... |
| CYPRUS | 94610.94 | ... | ... | ... |
| BELGIUM | 64971.85 | ... | ... | ... |
| BELARUS | 46903.82 | ... | ... | ... |
| OTHERS | 31896.98 | SUM here | SUM here | ... |
已有的变量定义:
# 需计算的历史日期(均为Timestamp类型) calculated_column_dates = [minus_one_day, minus_two_day, minus_three_day, minus_one_week, minus_four_week] # 今日确定的Top 10国家列表(不含OTHERS) top_countries = top10_df.Countries.tolist()
核心问题
- 最优实现方案是什么?是否需要循环每个国家和日期执行groupby/筛选?
- 如何计算指定日期下"OTHERS"的金额总和(即排除Top N国家后剩余金额的求和)?
解决方案:无循环的向量化处理
完全不需要循环操作,利用Pandas的分类转换、分组聚合和透视功能,高效完成需求,步骤如下:
1. 筛选目标日期数据集
先从原DataFrame中提取所有需要计算的日期(今日+历史日期),减少数据处理量:
# 假设原DataFrame名为df,先定义所有目标日期(含今日) today_date = pd.Timestamp.today().date() target_dates = [today_date] + [dt.date() for dt in calculated_column_dates] # 筛选出目标日期的数据 filtered_df = df[df.index.date.isin(target_dates)]
2. 统一国家分组规则
将非Top国家标记为"OTHERS",并转为分类类型以固定顺序:
import numpy as np # 定义分组类别:Top国家 + OTHERS country_groups = top_countries + ["OTHERS"] # 标记每个交易的分组:Top国家保留原名,其余归为OTHERS filtered_df["Country_Group"] = np.where( filtered_df["Countries"].isin(top_countries), filtered_df["Countries"], "OTHERS" ) # 转为分类类型,确保后续结果的国家顺序与Top列表一致 filtered_df["Country_Group"] = pd.Categorical( filtered_df["Country_Group"], categories=country_groups, ordered=True )
3. 聚合+透视生成目标表
按日期和分组求和,再转成宽表格式:
# 按日期和分组聚合金额 aggregated = filtered_df.groupby([filtered_df.index.date, "Country_Group"])["Amount"].sum().reset_index() # 透视成目标格式:行是国家/OTHERS,列是日期 result_df = aggregated.pivot(index="Country_Group", columns="index", values="Amount").reset_index() # 重命名列名为用户示例的格式(如"22 July 2022") result_df.columns = ["Country"] + [pd.to_datetime(col).strftime("%d %B %Y") for col in result_df.columns[1:]]
4. 缺失值处理(可选)
若部分日期下某分组无交易,填充为0:
result_df = result_df.fillna(0.0)
关键细节说明
- 避免循环的原因:循环每个日期/国家会导致大量重复计算,Pandas的向量化操作是底层优化的,处理大型数据集时效率提升明显。
- OTHERS的计算逻辑:通过
np.where一次性标记非Top国家,分组求和时自动聚合所有非Top国家的金额,无需额外筛选。 - 保持顺序:使用
pd.Categorical固定分组顺序,确保结果表中的国家顺序与你生成的Top列表完全一致,不会出现乱序。
内容的提问来源于stack exchange,提问作者mrGott
相关产品推荐
相关产品推荐

