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

如何用更Pythonic的方法按多列条件拆分订单运费金额

订单运费行维度分摊优化方案

需求背景

我们的线上订单数据仅在订单维度统计总运费,但财务人员需要将总运费拆分到行维度的多个供应商名下。
拆分运费时需遵循规则:

  • 未发货商品不参与运费分摊
  • 参与促销免运费的商品不参与运费分摊
    该需求此前是通过ODBC连接SQL数据库拉取数据后,使用Excel公式处理的,现有实现可正常输出结果,但希望找到更高效、更符合Pythonic规范的写法。

原有实现代码

import pandas as pd
import numpy as np

df = pd.DataFrame({'id': [10, 11, 11, 11, 12, 12, 13, 14, 15, 15],
                   'shipping': [5, 5, 5, 5, 5, 5, 0, 0, 5, 5],
                   'shipstatus': [True, True, True, False,
                   True, True, False, True, True, True],
                   'freeship': [False, True, False, False,
                   False, False, False, True, False, False]})

df['a'] = df.groupby(['id','shipstatus','freeship'])['shipping'].transform('count')
# 原逻辑按id、发货状态、是否免运费分组统计数量,避免免运费商品被计入分摊基数
df['b'] = df['a'] * (df['freeship']==False) 
# 免运费商品的分摊基数直接置0
df['c'] = df['shipping']/df['b'] 
# 计算单条商品分摊运费,这里会出现除以0导致的inf、运费为0导致的NaN
df['LineShipping'] = df['shipstatus'] * (df['freeship']==False) * df['c']
# 不符合分摊条件的行直接置0
df = df.fillna(0) 
# 处理异常值
df = df.drop(columns=['a','b','c']) 
# 删除临时列

print(df)

优化后实现

原有逻辑是正确的,我们可以简化中间临时变量的生成,通过分组统计+条件赋值直接实现,代码更简洁,运行效率也更高:

import pandas as pd
import numpy as np

df = pd.DataFrame({'id': [10, 11, 11, 11, 12, 12, 13, 14, 15, 15],
                   'shipping': [5, 5, 5, 5, 5, 5, 0, 0, 5, 5],
                   'shipstatus': [True, True, True, False,
                                  True, True, False, True, True, True],
                   'freeship': [False, True, False, False,
                                False, False, False, True, False, False]})

# 标记符合分摊条件的行
eligible = df['shipstatus'] & (~df['freeship'])
# 按订单id分组,统计每个订单下符合分摊条件的商品数
df['eligible_cnt'] = eligible.groupby(df['id']).transform('sum')
# 直接按条件生成分摊运费,自动规避异常值
df['LineShipping'] = np.where(eligible & (df['eligible_cnt'] > 0), 
                              df['shipping'] / df['eligible_cnt'], 
                              0)
# 删除临时计数列
df = df.drop('eligible_cnt', axis=1)

print(df)

优化点说明

  • 仅生成1个临时计数列,内存占用更低
  • 用np.where直接处理条件分支,避免了除以0产生的inf、运费为0产生的NaN问题,不需要额外调用fillna
  • 逻辑更直观,可读性更高,完全符合pandas的常用写法规范

输出结果

运行优化后代码得到的结果和预期完全一致,如下:

idshippingshipstatusfreeshipLineShipping
105TrueFalse5.0
115TrueTrue0.0
115TrueFalse5.0
115FalseFalse0.0
125TrueFalse2.5
125TrueFalse2.5
130FalseFalse0.0
140TrueTrue0.0
155TrueFalse2.5
155TrueFalse2.5

内容的提问来源于stack exchange,提问作者John Henry Erikson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 01:06:08