You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python的Pandas DataFrame中按条件生成Other计算行

Pandas DataFrame中生成「Other」行的最优实现方法

需求说明

需要为每个Name分组生成「Other」行,计算逻辑为:Other = Total - (Source_1 + Source_2 + Source_3),即Total行的数值减去同组内所有非Total Source的数值之和。

初始数据

NameSourceLeadSale
Prop_ASource_11003
Prop_ASource_2505
Prop_ASource_3200
Prop_ATotal30011
Prop_BSource_120010
Prop_BSource_23006
Prop_BSource_3200
Prop_BTotal70023

目标结果

NameSourceLeadSale
Prop_ASource_11003
Prop_ASource_2505
Prop_ASource_3200
Prop_AOther1303
Prop_ATotal30011
Prop_BSource_120010
Prop_BSource_23006
Prop_BSource_3200
Prop_BOther1807
Prop_BTotal70023

原实现代码

Total_df = df[df['Source'] == 'Total']
All_Sources_df = df[df['Source'] != 'Total']

All_Sources_df = All_Sources_df.groupby(['Name'], as_index=False).sum()

result = pd.merge(Total_df, All_Sources_df, on=['Name'])

result['Lead'] =  result['Lead_x'] - result['Lead_y']
result['Sale'] =  result['Sale_x'] - result['Sale_y']

result = result[['Name', 'Lead', 'Sale']]

result['Source'] = 'Other'

result = result[['Name','Source','Lead','Sale']]

优化实现方案

以下两种方案更简洁高效,减少中间变量,逻辑更连贯:

方案一:链式调用+合并

利用merge结合assign链式生成Other行,再通过concat合并所有数据,避免多次列重排操作:

import pandas as pd

# 构造示例数据(实际使用时替换为你的df)
data = [
    ['Prop_A', 'Source_1', 100, 3],
    ['Prop_A', 'Source_2', 50, 5],
    ['Prop_A', 'Source_3', 20, 0],
    ['Prop_A', 'Total', 300, 11],
    ['Prop_B', 'Source_1', 200, 10],
    ['Prop_B', 'Source_2', 300, 6],
    ['Prop_B', 'Source_3', 20, 0],
    ['Prop_B', 'Total', 700, 23]
]
df = pd.DataFrame(data, columns=['Name', 'Source', 'Lead', 'Sale'])

# 1. 分离Total和非Total行
total_rows = df[df['Source'] == 'Total']
non_total_rows = df[df['Source'] != 'Total']

# 2. 计算非Total行的分组总和,生成Other行
other_rows = (
    total_rows.merge(non_total_rows.groupby('Name')[['Lead', 'Sale']].sum().reset_index(), on='Name')
    .assign(
        Lead=lambda x: x['Lead_x'] - x['Lead_y'],
        Sale=lambda x: x['Sale_x'] - x['Sale_y'],
        Source='Other'
    )[['Name', 'Source', 'Lead', 'Sale']]
)

# 3. 合并并排序
final_df = pd.concat([non_total_rows, other_rows, total_rows])\
    .sort_values(['Name', 'Source'])\
    .reset_index(drop=True)

# 调整Source顺序,把Total移到最后(可选)
final_df['Source'] = pd.Categorical(
    final_df['Source'],
    categories=['Source_1', 'Source_2', 'Source_3', 'Other', 'Total'],
    ordered=True
)
final_df = final_df.sort_values(['Name', 'Source']).reset_index(drop=True)

print(final_df)

方案二:透视表重塑(适合Source固定的场景)

如果Source的类型固定(比如只有Source_1/2/3和Total),可以用pivot_table快速计算,再重塑回原格式:

import pandas as pd

# 构造示例数据
df = pd.DataFrame(data, columns=['Name', 'Source', 'Lead', 'Sale'])

# 1. 透视表分组计算
pivot = df.pivot_table(
    index='Name',
    columns='Source',
    values=['Lead', 'Sale'],
    aggfunc='sum'
)
pivot.columns = ['_'.join(col) for col in pivot.columns]

# 2. 计算Other值
pivot['Lead_Other'] = pivot['Lead_Total'] - pivot[['Lead_Source_1', 'Lead_Source_2', 'Lead_Source_3']].sum(axis=1)
pivot['Sale_Other'] = pivot['Sale_Total'] - pivot[['Sale_Source_1', 'Sale_Source_2', 'Sale_Source_3']].sum(axis=1)

# 3. 重塑回原格式
final_df = (
    pivot.unstack().reset_index(name='Value')
    .rename(columns={'level_0': 'Metric', 'Source': 'Source'})
    .pivot(index=['Name', 'Source'], columns='Metric', values='Value')
    .reset_index()
    [['Name', 'Source', 'Lead', 'Sale']]
)

# 调整Source顺序
final_df['Source'] = pd.Categorical(
    final_df['Source'],
    categories=['Source_1', 'Source_2', 'Source_3', 'Other', 'Total'],
    ordered=True
)
final_df = final_df.sort_values(['Name', 'Source']).reset_index(drop=True)

print(final_df)

优化优势

  • 减少中间变量:用链式调用替代多个独立的DataFrame赋值,代码更简洁易读
  • 逻辑连贯:从计算到合并的流程一气呵成,降低出错概率
  • 效率提升:避免不必要的列选择和重排操作,大数据量下性能更优

内容的提问来源于stack exchange,提问作者Juana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 13:05:17