如何按Deal分组并依多条件汇总不同Currency的金额数据
行级条件数据汇总优化方案
需求明确
- 按
Deal字段分组进行数据计算 - 同一
Currency下,执行自定义计算:(Investment金额总和 + Capital金额总和) - (Borrow金额总和 + Interest金额总和) - 不同
Currency需独立计算,不可混同 - 仅当某
Deal包含全部4种Flow类型(Investment、Borrow、Interest、Capital)时,才对该Deal执行计算
示例输入数据
import pandas as pd data = { 'Deal': [1,1,1,1,2,2,2,2,3,3,3,4,4,4,4], 'Flow': ['Investment','Borrow','Interest','Capital', 'Investment','Borrow','Interest','Capital', 'Investment','Borrow','Interest', 'Investment','Borrow','Interest','Capital'], 'Amount': [100,10,5,50,100,10,5,50,100,10,5,100,10,5,50], 'Currency': ['USD','USD','USD','EUR','USD','USD','USD','USD','USD','EUR','USD','USD','EUR','USD','USD'] } df = pd.DataFrame(data)
对应的DataFrame展示:
Deal Flow Amount Currency 0 1 Investment 100 USD 1 1 Borrow 10 USD 2 1 Interest 5 USD 3 1 Capital 50 EUR 4 2 Investment 100 USD 5 2 Borrow 10 USD 6 2 Interest 5 USD 7 2 Capital 50 USD 8 3 Investment 100 USD 9 3 Borrow 10 EUR 10 3 Interest 5 USD 11 4 Investment 100 USD 12 4 Borrow 10 EUR 13 4 Interest 5 USD 14 4 Capital 50 USD
期望输出
Deal Amount Currency Amount Currency 0 1 85 USD 50.0 EUR 1 2 135 USD NaN None 2 4 145 USD -10.0 EUR
实现方案(基于Pandas)
步骤1:筛选符合条件的Deal
先过滤出包含全部4种Flow类型的Deal,减少无效计算:
# 定义必须包含的Flow类型集合 required_flows = {'Investment', 'Borrow', 'Interest', 'Capital'} # 检查每个Deal是否覆盖所有必需Flow类型 valid_deals = df.groupby('Deal')['Flow'].apply( lambda x: required_flows.issubset(x.unique()) ).reset_index() # 提取有效Deal的ID列表 valid_deal_ids = valid_deals[valid_deals['Flow']]['Deal'].tolist() # 过滤原数据到仅包含有效Deal的子集 df_valid = df[df['Deal'].isin(valid_deal_ids)]
步骤2:按Deal+Currency分组执行自定义计算
对每个有效Deal下的不同Currency,分别计算目标金额:
def calculate_target_amount(group): # 计算Investment与Capital的总和 invest_cap_sum = group[group['Flow'].isin(['Investment', 'Capital'])]['Amount'].sum() # 计算Borrow与Interest的总和 borrow_int_sum = group[group['Flow'].isin(['Borrow', 'Interest'])]['Amount'].sum() # 返回最终计算结果 return invest_cap_sum - borrow_int_sum # 分组计算结果 calculated_result = df_valid.groupby(['Deal', 'Currency']).apply( calculate_target_amount ).reset_index(name='Calculated_Amount')
步骤3:转换为期望的宽表格式
将分组后的长表转换为多列并排的宽表,匹配输出要求:
# 给每个Deal下的Currency结果添加序号,用于转宽表 calculated_result['seq'] = calculated_result.groupby('Deal').cumcount() # 转宽表,拆分不同Currency的结果为多列 wide_result = calculated_result.pivot( index='Deal', columns='seq', values=['Calculated_Amount', 'Currency'] ) # 重命名列,调整为直观的格式 wide_result.columns = [ f'{col[0]}_{col[1]+1}' if col[1] != 0 else col[0] for col in wide_result.columns ] # 调整列顺序,实现Amount与Currency交替排列 col_order = [] for i in range(len(wide_result.columns)//2): col_order.append(f'Calculated_Amount_{i+1}' if i>0 else 'Calculated_Amount') col_order.append(f'Currency_{i+1}' if i>0 else 'Currency') wide_result = wide_result[col_order] # 重置索引、填充缺失值,并重命名列匹配期望输出 final_result = wide_result.reset_index().fillna({ 'Calculated_Amount': pd.NA, 'Currency': None }) final_result.columns = ['Deal', 'Amount', 'Currency', 'Amount', 'Currency'] # 打印最终结果 print(final_result)
方案优势
- 高效性:先筛选有效Deal,避免对不符合条件的数据执行无效计算,提升处理效率
- 灵活性:自定义计算函数可轻松调整逻辑,适配后续需求变化
- 可读性:步骤拆分清晰,代码逻辑明确,便于维护和扩展
内容的提问来源于stack exchange,提问作者Pavan Kumar Polavarapu
相关产品推荐
相关产品推荐

