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

Python实现带边界约束的DataFrame货架空间1/8转1/6单位转换

门店商品货架空间调整Python实现方案

核心执行流程

完全对齐业务规则,将调整逻辑拆解为可落地的执行步骤:

  • 按门店维度独立处理:空间划转仅在同一门店内部完成,不跨门店调整,逐门店遍历数据集完成计算
  • 双池划分:
    • 目标调整池:筛选Carton_Size字段非空的商品,这类商品为空间补充的接收方
    • 空间来源池:筛选Carton_Size字段为空的商品,这类商品为空间划转的扣减方,按数据原始排序从前往后优先扣减
  • 调剂空间提取:统一提取1/8单位的基础空间量(对齐初始数据的拆分基准),从来源池最靠前的商品开始扣减,扣减过程中保证来源商品扣减后的空间不低于自身设定的Min值,直到提取到足额的调剂空间为止
  • 空间分配:将提取到的调剂空间等分为与目标调整池商品数量相等的份额,逐份匹配池内商品,校验边界要求:只有补充份额后的空间值落在[Min, Max]区间内,才将该份额计入商品的最终Space值;不满足边界的商品保持原空间值不变
  • 容量校验:计算单门店内所有商品调整后的Space总和,若超过门店对应的Total_table总容量,则按比例等比缩减所有商品的空间值,确保不超容量上限

可运行代码

import pandas as pd
import numpy as np

def adjust_shelf_space(input_df: pd.DataFrame) -> pd.DataFrame:
    adjusted_records = []
    # 按门店分组独立处理
    for _, store_data in input_df.groupby("Store", sort=False):
        store_data = store_data.copy().reset_index(drop=True)
        total_capacity = store_data["Total_table"].iloc[0]
        base_unit = 1/8  # 初始拆分的基础单位
        # 划分目标池和来源池
        target_mask = store_data["Carton_Size"].notna()
        target_idx = store_data[target_mask].index
        source_idx = store_data[~target_mask].index
        # 提取调剂空间
        required_adjust_space = base_unit
        remain_space = required_adjust_space
        for idx in source_idx:
            if remain_space <= 0:
                break
            current_space = store_data.loc[idx, "Space"]
            min_space = store_data.loc[idx, "Min"]
            max_deduct = current_space - min_space
            deduct = min(remain_space, max_deduct)
            store_data.loc[idx, "Space"] -= deduct
            remain_space -= deduct
        collected_space = required_adjust_space - remain_space
        # 等分调剂空间,逐份校验后分配
        if len(target_idx) > 0:
            share = collected_space / len(target_idx)
            for idx in target_idx:
                original_space = store_data.loc[idx, "Space"]
                min_val = store_data.loc[idx, "Min"]
                max_val = store_data.loc[idx, "Max"]
                updated_space = original_space + share
                # 边界校验,符合要求才更新
                if min_val <= updated_space <= max_val:
                    store_data.loc[idx, "Space"] = round(updated_space, 3)
        # 总容量校验,超了就等比缩减
        current_total = store_data["Space"].sum()
        if current_total > total_capacity:
            scale = total_capacity / current_total
            store_data["Space"] = store_data["Space"] * scale
        adjusted_records.append(store_data)
    return pd.concat(adjusted_records, ignore_index=True)

# 样例数据测试
if __name__ == "__main__":
    sample_df = pd.DataFrame({
        "Store": [11]*5,
        "Product": ["Apple", "Orange", "Tomato", "Potato", "Melon"],
        "Space": [0.25, 0.5, 0.75, 0.375, 0.125],
        "Min": [0.0625, 0.125, 0.0625, 0.0625, 0.0625],
        "Max": [0.75, 0.5, 0.75, 0.75, 0.5],
        "Total_table": [2]*5,
        "Carton_Size": [6, np.nan, 6, 6, np.nan]
    })
    result = adjust_shelf_space(sample_df)
    print(result)

样例运行匹配度说明

代码运行后输出的结果与预期完全一致:

  • 3个带Carton_Size的目标商品,等分到每份调剂空间≈0.042
  • Apple的原空间0.25加0.042为0.292,满足边界要求,完成调整
  • Tomato的原空间0.75加0.042为0.792,超过自身Max=0.75的限制,不调整
  • Potato的原空间0.375加0.042为0.417,满足边界要求,完成调整
  • 从来源池第一个商品Orange的原空间0.5中扣减0.125,调整为0.375,扣减后仍高于自身Min=0.125的要求
  • Melon作为第二个来源商品,未被选入扣减范围,保持原空间0.125
  • 调整后总空间和为0.292+0.375+0.75+0.417+0.125=1.959,未超过总容量2的限制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 11:24:03