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

如何对多层索引Pandas DataFrame外层索引行求和及筛选最优商品组合

问题解决思路与代码实现

一、优化前期数据处理(替代低效的iterrows)

用矢量化操作替代循环,提升代码效率:

import pandas as pd
import numpy as np

# 示例数据
item1 = ['item 1', 'item 2', 'item 1', 'item 1', 'item 2']
seller1 = ['Seller 1', 'Seller 2', 'Seller 3', 'Seller 4', 'Seller 1']
price1 = [1.85, 1.94, 2.00, 2.00, 2.02]
shipping1 = [0.99, 0.99, 0.99, 2.99, 0.99]
freeship1 = [5, 5, 5, 50, 5]
countavailable1 = [1, 2, 2, 5, 2]
countneeded1 = [2, 1, 2, 2, 1]

df1 = pd.DataFrame({
    "Seller": seller1,
    "Item": item1,
    "Price": price1,
    "Shipping": shipping1,
    "Free Shipping Minimum": freeship1,
    "Count Available": countavailable1,
    "Count Needed": countneeded1
})

# 1. 判断是否满足所需数量
df1['Fulfills Count Needed'] = np.where(df1['Count Available'] >= df1['Count Needed'], 'Yes', 'No')

# 2. 计算商品总金额(取可提供数量与所需数量的最小值相乘)
df1['Price x Count'] = np.minimum(df1['Count Available'], df1['Count Needed']) * df1['Price']

二、按卖家分组计算总花费(正确处理运费与免邮)

解决同一卖家运费重复计算的问题,先按卖家聚合商品总金额,再应用免邮规则:

# 按卖家分组,聚合核心字段
seller_group = df1.groupby('Seller').agg(
    Total_Goods_Price=('Price x Count', 'sum'),
    Shipping_Cost=('Shipping', 'first'),  # 假设同一卖家运费规则统一
    Free_Shipping_Min=('Free Shipping Minimum', 'first'),
    Item_Details=('Item', list),
    Item_Counts=('Price x Count', lambda x: list(x / df1.loc[x.index, 'Price']))  # 还原实际可购买数量
).reset_index()

# 计算实际运费:满足免邮门槛则免运费,否则收取基础运费
seller_group['Actual_Shipping'] = np.where(
    seller_group['Total_Goods_Price'] >= seller_group['Free_Shipping_Min'],
    0,
    seller_group['Shipping_Cost']
)

# 计算卖家总花费(商品金额+运费)
seller_group['Total_Cost'] = seller_group['Total_Goods_Price'] + seller_group['Actual_Shipping']

三、选取刚好满足需求的低价商品组合(贪心算法)

采用贪心策略:优先选择能覆盖更多需求、单位成本更低的卖家,逐步补充直到满足所有需求:

# 1. 定义全局需求(可根据实际场景调整)
global_needs = {'item 1': 2, 'item 2': 2}

# 2. 计算每个卖家的需求覆盖量和单位成本
def calculate_contribution(row):
    total_contrib = 0
    total_units = 0
    # 遍历卖家的商品,计算能覆盖的需求数量
    for item, count in zip(row['Item_Details'], row['Item_Counts']):
        if item in global_needs:
            contrib = min(count, global_needs[item])
            total_contrib += contrib
            total_units += contrib
    # 计算单位成本(无可用商品则设为无穷大)
    unit_cost = row['Total_Cost'] / total_units if total_units > 0 else float('inf')
    return pd.Series([total_contrib, unit_cost], index=['Total_Contribution', 'Unit_Cost'])

seller_group[['Total_Contribution', 'Unit_Cost']] = seller_group.apply(calculate_contribution, axis=1)

# 3. 排序卖家:优先覆盖需求多的,其次单位成本低的
seller_sorted = seller_group.sort_values(by=['Total_Contribution', 'Unit_Cost'], ascending=[False, True])

# 4. 贪心选取卖家,直到满足所有需求
selected_sellers = []
remaining_needs = global_needs.copy()

for _, row in seller_sorted.iterrows():
    if all(v <= 0 for v in remaining_needs.values()):
        break
    
    seller_items = dict(zip(row['Item_Details'], row['Item_Counts']))
    purchase = {}
    purchase_goods_cost = 0
    
    # 计算本次从该卖家购买的商品数量和金额
    for item, need in remaining_needs.items():
        if need <= 0 or item not in seller_items:
            continue
        buy_count = min(seller_items[item], need)
        purchase[item] = buy_count
        remaining_needs[item] -= buy_count
        # 获取该商品单价,计算本次购买的商品成本
        item_price = df1[(df1['Seller'] == row['Seller']) & (df1['Item'] == item)]['Price'].iloc[0]
        purchase_goods_cost += item_price * buy_count
    
    # 计算本次订单的运费
    if purchase_goods_cost >= row['Free_Shipping_Min']:
        shipping_cost = 0
    else:
        shipping_cost = row['Shipping_Cost']
    total_order_cost = purchase_goods_cost + shipping_cost
    
    if purchase:
        selected_sellers.append({
            'Seller': row['Seller'],
            'Purchased_Items': purchase,
            'Order_Total_Cost': total_order_cost
        })

# 输出结果
print("Selected Seller Orders:")
for order in selected_sellers:
    print(f"Seller: {order['Seller']}, Purchased: {order['Purchased_Items']}, Total Cost: ${order['Order_Total_Cost']:.2f}")

total_overall = sum(order['Order_Total_Cost'] for order in selected_sellers)
print(f"\nOverall Total Cost: ${total_overall:.2f}")

示例输出

Selected Seller Orders:
Seller: Seller 1, Purchased: {'item 1': 1, 'item 2': 1}, Total Cost: $4.85
Seller: Seller 3, Purchased: {'item 1': 1}, Total Cost: $2.99
Seller: Seller 2, Purchased: {'item 2': 1}, Total Cost: $2.93

Overall Total Cost: $10.77

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 12:05:09