【促销定价】背后的算法技术 2 - 数据预处理生成

【促销定价】背后的算法技术 2 - 数据预处理生成

    • 01 数据探查
    • 02 数据清洗
    • 03 数据聚合
    • 04 数据补全
    • 05 小结
    • 参考文献

导读:在日常生活中,我们经常会遇见线上/线下商家推出各类打折、满减、赠品、新人价、优惠券、捆绑销售等促销活动。一次成功的促销对于消费者和商家来说是双赢的。一方面,促销活动能让消费者买到低价的商品;另一方面,促销活动也能为商家带来可观的利润。因此,对于商家来说,如何科学合理地制定促销策略是必须仔细思考的问题。


作者1:张哲铭,算法专家,某互联网大厂
作者2:向杜兵,算法专家,某制造业龙头


大家好!我们是IndustryOR团队,致力于分享业界落地的OR+AI技术。欢迎关注微信公众号/知乎【运筹匠心】 。本期我们来谈一谈《促销定价背后的算法技术》。促销活动五花八门、玩法多变,但其底层的核心商业逻辑是“价格”。因此,本期案例将选择某零售商超“促销定价”场景,共分5篇文章依次讲解:(1)业务问题拆解;(2)数据预处理生成;(3)数据挖掘分析;(4)模型算法实现-价格弹性模型;(5)模型算法实现-运筹决策模型。

本篇文章讲解(2)数据预处理生成

共分为5个部分,依次为:
01 数据探查
02 数据清洗
03 数据聚合
04 数据补全
05 小结

注:本案例数据改编自【2019年全国大学生数学建模E题】公开数据集。


01 数据探查

本案例主要用到销售流水表1/2(附件1/2)和商品信息表(附件4),表结构如下:

  • 销售流水表
字段含义
order_id订单ID
is_finished订单是否完成
sku_id商品ID
sku_name商品名称
sku_prc门店价
sku_sale_prc销售价
sku_cost_prc成本价
sku_cnt销售数量
upc_codeUPC码
create_dt创建时间
  • 商品信息表
字段含义
skuidsku名称
skunamesku名称
first_category_id一级类目id
second_category_id二级类目id
third_category_id三级类目id
first_category_name一级类目名称
second_category_name二级类目名称
third_category_name三级类目名称

1)数据加载

# 读取订单明细表、sku明细表  
order_detail_df1 = pd.read_csv('附件1.txt', sep=',', encoding='utf8')  
order_detail_df2 = pd.read_csv('附件2.txt', sep=',', encoding='utf8')  
sku_detail_df = pd.read_csv('附件4.txt', sep=',', encoding='utf8')  

注:原数据文件是excel,笔者将其转成的txt,同学在复现时需要注意一下这里

2)数据概览

图片图片图片

<<< 左右滑动见更多 >>>

我们发现:销售流水表upc_code字段部分缺失,其他字段不缺失。商品信息表无缺失字段。

3)数据细节

图片


02 数据清洗

1)合并销售流水表,并拼接商品信息表

# 合并订单明细表  
order_detail_df = pd.concat(objs=[order_detail_df1, order_detail_df2], axis=0)  
# 拼接sku明细表  
data_df = pd.merge(left=order_detail_df, right=sku_detail_df, on=['sku_id','sku_name'], how='left')  

2)合并之后探查整体数据

图片我们发现:销售流水表共有1221855条订单商品(SKU)流水信息,有类目信息的有804158条。

3)异常样本过滤

首先过滤掉类目为空的SKU,再剔除掉未完单的样本,最后剔除销量、门店价、销售价、成本价为负的样本。代码如下:

# 异常样本过滤  
data_df = data_df[~data_df['third_category_id'].isnull()] # 过滤类项目信息为空的sku  
data_df = data_df[data_df['is_finished'] == 1] # 剔除未完单样本  
data_df = data_df[(data_df['sku_cnt'] >= 0) & (data_df['sku_sale_prc'] >= 0) & \  
(data_df['sku_prc'] >= 0 )  & (data_df['sku_cost_prc'] >= 0 )] # 剔除销量、价格<=0样本  


03 数据聚合

1)将SKU流水数据合并到天,销量取和,价格取均值

# 订单聚合至sku日流水  
data_df = data_df.\  
groupby(['create_dt', 'sku_id', 'sku_name', 'first_category_id', 'second_category_id', 'third_category_id', 'first_category_name', 'second_category_name', 'third_category_name']).\  
agg({'sku_cnt':'sum', 'sku_prc':'mean', 'sku_sale_prc':'mean'}).reset_index()  

2)将日期格式转换为YYYY-MM-DD格式,以便于排序

# create_dt日期格式转换  
data_df['create_dt'] = data_df.apply(func=IOR_DP.date_style_convert, axis=1)  

3)对数据进行排序,以便观察

# 排序  
data_df = data_df.sort_values(by=['sku_id', 'create_dt'], ascending=[True,True]).reset_index(drop=True,inplace=False)  

4)避开长假,截取2018-03-01至2018-09-30的数据进行研究

# 截取非长假半年时间段  
data_df = data_df[(data_df['create_dt'] >= '2018-03-01') & (data_df['create_dt'] <= '2018-09-30')]  

5)对数据统一进行重命名

# 列原名太长,重命名  
data_df = data_df.rename(columns={'first_category_id':'cate1_id', 'first_category_name':'cate1_name', \  
                                 'third_category_id':'cate3_id', 'third_category_name':'cate3_name', \  
                                 'sku_prc':'ori_prc','sku_sale_prc':'sale_prc', 'sku_cnt':'sale_cnt', 'create_dt': 'sale_dt'})  


04 数据补全

1)由于成本价缺失严重,因此进行补全操作

根据数据集提示:零售商的毛利率大概在0.2-0.4之间。因此,可先生成毛利率,然后用门店价(原价)、销售价(折扣价)反推成本价。步骤如下:

  • 假设原价相较成本价的毛利率符合正态分布,最大值为0.4,最小值为0.2;

  • 假设折扣价相较成本价的毛利率符合正态分布,最大值为0.05,最小值为0.35;

  • 成本价 = (原价反推的成本价,折扣价反推的成本价)

注:实际业务中,价格大概率不符合正态分布,需要用真实数据。

# 原数据成本价异常(大部分缺失,未缺失的与折扣价相同),无法使用,需要重新制作  
## 一个sku历史一个成本价,暂不考虑波动,简化处理  
cost_prc_df = data_df[['sku_id', 'ori_prc', 'sale_prc']].\  
groupby(['sku_id']).agg({'ori_prc':'mean', 'sale_prc':'mean'}).reset_index()   
  
## 正态分布造原价毛利N(0.3,0.05)、折扣价毛利N(0.2,0.05)  
ori_prc_profit_ratio_array = IOR_DP.generate_norm_data(mean = 0.3, std = 0.05, x_min = 0.2, x_max = 0.4, n = len(cost_prc_df))  
sale_prc_profit_ratio_array = IOR_DP.generate_norm_data(mean = 0.2, std = 0.05, x_min = 0.05, x_max = 0.35, n = len(cost_prc_df))  
  
## 制作成本价,保证要比折扣价低,不能赔本卖  
cost_prc_df['ori_prc_profit_ratio'] = ori_prc_profit_ratio_array  
cost_prc_df['sale_prc_profit_ratio'] = sale_prc_profit_ratio_array  
cost_prc_df['ori_prc_cost_prc'] = cost_prc_df['ori_prc'] / (cost_prc_df['ori_prc_profit_ratio'] + 1) # 原价反推的成本价  
cost_prc_df['sale_prc_cost_prc'] = cost_prc_df['sale_prc'] / (cost_prc_df['sale_prc_profit_ratio'] + 1) # 折扣价反推的成本价  
cost_prc_df['cost_prc'] = cost_prc_df.apply(func=lambda x: min(x['ori_prc_cost_prc'], x['sale_prc_cost_prc']), axis=1) # 取小者  
data_df = pd.merge(left=data_df, right=cost_prc_df[['sku_id', 'cost_prc']], on=['sku_id'], how='left') # 拼接回主表  

2)最后修改特征字段类型并输出至csv

# 修改列类型、小数点后位数、展示顺序  
data_df['sku_id'] = data_df['sku_id'].astype('int')  
data_df['cate1_id'] = data_df['cate1_id'].astype('int')  
data_df['cate2_id'] = data_df['cate2_id'].astype('int')  
data_df['cate3_id'] = data_df['cate3_id'].astype('int')  
data_df['sale_cnt'] = data_df['sale_cnt'].astype('int')  
data_df['ori_prc'] = data_df['ori_prc'].astype('float').round(2)  
data_df['sale_prc'] = data_df['sale_prc'].astype('float').round(2)  
data_df['cost_prc'] = data_df['cost_prc'].astype('float').round(2)  
data_df = data_df[['sku_id', 'sku_name', 'ori_prc', 'sale_prc', 'cost_prc', 'sale_cnt', 'cate1_id', 'cate2_id', 'cate3_id', 'cate1_name', 'cate2_name', 'cate3_name', 'sale_dt']]  
# 输出  
data_df.to_csv('promotional_pricing_data1.csv', sep=',', encoding='utf8', index=False)  


05 小结

第一篇(业务问题拆解):我们把一个实际的促销定价问题拆解成了一系列的数学问题。

本篇(数据预处理生成):我们选择了一份公开的促销定价数据集,将其加工成了可分析求解的数据。

下一篇(数据挖掘分析):我们将介绍如何对数据进行全方位的挖掘和分析。敬请期待~~~


参考文献

  1. Hua J, Yan L, Xu H,et al. Markdowns in E-Commerce Fresh Retail: A Counterfactual Prediction and Multi-Period Optimization Approach[J]. arxiv, 2021.(https://arxiv.org/pdf/2105.08313.pdf)

  2. Kui Zhao, Junhao Hua, Ling Yan, et al. A Unified Framework for Marketing Budget Allocation[J]. arxiv, 20.(https://arxiv.org/pdf/1902.01128.pdf)

  3. 用相关系数进行Kmeans聚类,利用利润率、打折率、销售额、毛利润得到商品价格弹性标签,建立价格折扣力度模型(https://blog.csdn.net/weixin_45934622/article/details/114382037)

  4. 2019全国大学生数学建模竞赛讲评:“薄利多销”分析(https://dxs.moe.gov.cn/zx/a/hd_sxjm_sxjmstjp_2019sxjmstjp/210604/1699445.shtml)

  5. 策略算法工程师之路-基于线性规划的简单价格优化模型(https://zhuanlan.zhihu.com/p/145192690)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/319577.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux 内核源码分析笔记】系统调用

在Linux内核中&#xff0c;系统调用是用户空间程序与内核之间的接口&#xff0c;它允许用户空间程序请求内核执行特权操作或访问受保护的内核资源。系统调用提供了一种安全可控的方式&#xff0c;使用户程序能够利用内核功能而不直接访问底层硬件。 系统调用&#xff1a; 通过…

Azure Machine Learning - 视频AI技术

Azure AI 视频索引器是构建在 Azure 媒体服务和 Azure AI 服务&#xff08;如人脸检测、翻译器、Azure AI 视觉和语音&#xff09;基础之上的一个云应用程序&#xff0c;是 Azure AI 服务的一部分。 有了 Azure 视频索引器&#xff0c;就可以使用 Azure AI 视频索引器视频和音频…

Fastadmin上传图片服务端压缩图片,实测13.45M压缩为29.91K

先前条件&#xff1a;第一步安装compose&#xff0c;已安装忽略。 先上截图看效果 一、在fastadmin的根目录里面输入命令安装think-image composer require topthink/think-image二、找到公共上传类&#xff0c;application/common/library/Upload.php&#xff0c;在最下面…

Java SE入门及基础(12)

do-while 循环 1. 语法 do { //循环操作 } while ( 循环条件 ); 2. 执行流程图 3. 案例 从控制台录入学生的成绩并计算总成绩&#xff0c;输入0 时退出 4. 代码实现 public static void main ( String [] args ) { Scanner sc new Scanner ( System . in )…

大面积光源HUD阳光倒灌实验装置太阳光模拟器

背景 1.根据现在市场上一些量产的hud的结构和原理可知&#xff0c;hud中最重要的零件之一就是凹面镜(自由曲面)&#xff0c;hud利用凹面镜放大投影的光学原理进行投影成像。当发生阳光倒灌时&#xff0c;太阳光沿着hud正常工作时成像的逆光路&#xff0c;通过挡风玻璃-凹面镜-…

豆包ai介绍

豆包是字节跳动基于云雀模型开发的AI工具&#xff0c;具有强大的语言处理能力和广泛的应用场景&#xff0c;无论是在学习、工作、生活中&#xff0c;都能派上用场。 豆包可以帮助打工人和创作者提升效率&#xff0c;完成各种工作任务&#xff0c;又能扮演各类AI角色进行高情商…

MySQL简介、安装及使用

一、MySQL简介 1、MySQL的介绍 MySQL数据库管理系统由瑞典的DataKonsultAB公司研发&#xff0c;该公司被Sun公司收购&#xff0c;现在Sun公司又被Oracle公司收购&#xff0c;因此MySQL目前属于 Oracle 旗下产品。 MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言…

【Python学习】Python学习17- File(文件) 方法

目录 [TOC](【Python学习】Python学习17- File(文件) 方法) 文章所属专区 Python学习 前言 本章节主要说明Python文件操作的具体说明 open()方法 Python open() 方法用于打开一个文件&#xff0c;并返回文件对象&#xff0c;在对文件进行处理过程都需要使用到这个函数&#…

CnosDB的数据更新和删除

在时序数据中&#xff0c;可能会出现一些数据错误或者异常情况&#xff0c;这时候就需要能够对数据进行清洗修复。如果不支持更新操作&#xff0c;将会变得非常困难。另外&#xff0c;一些业务场景可能会需要对已有数据进行调整&#xff0c;比如设备信息发生变化等。支持数据更…

Python开源项目周排行 2024年第2周

点赞关注转发三连&#xff0c;您的支持是我的动力&#xff01; Python 趋势周报&#xff0c;按周浏览往期 GitHub,Gitee 等最热门的Python开源项目&#xff0c;入选的项目主要参考GitHub Trending,部分参考了Gitee和其他。排名不分先后&#xff0c;都是当周相对热门的项目。 …

12.3在应用层使用SPI总线

在SPI总线驱动框架中提供了一个spidev 的字符设备驱动&#xff0c;在应用层可以通过它来访问SPI总线。 应用层访问SPI总线的步骤 编写spidev设备树节点&#xff0c;在SPI总线的设备树节点下添加spidev设备的树节点&#xff0c;设备树示例如下所示&#xff1a; spidev0: spid…

《射雕三部曲》人物关系可视化及问答系统

背景&#xff1a; 该项目旨在构建一个基于图数据库和知识图谱的《射雕三部曲》人物关系可视化及问答系统。通过分析小说中的人物关系&#xff0c;将其构建成图数据库&#xff0c;并结合问答系统和数据分析技术&#xff0c;提供用户可视化的人物关系展示和相关问题的回答。 介绍…

Altium Desigenr 丝印重叠报错 规则修改1

Altium Desigenr画板时如果两个元件放的太近会变绿违反规则&#xff0c;特别实在有元器件外框同时需要减少PCB面积。两个电阻丝印紧挨报错&#xff0c;本质上不会影响但会报错。 1、首先在规则里面改小 2、如果不满足依旧报错&#xff0c;直接关闭元件放置规则&#xff0c;但…

宠物空气净化器哪个牌子好?实惠的猫用空气净化器牌子推荐

对于养猫的朋友来说&#xff0c;猫咪掉毛绝对是一个让人头痛的问题。猫毛和皮屑会飘散在空气中&#xff0c;不仅会遍布全屋的各个角落&#xff0c;而且打扫起来也麻烦&#xff0c;特别是一些清理不了的猫毛&#xff0c;甚至还可能引起人的过敏反应&#xff0c;例如咳嗽和哮喘。…

Unity组件开发--UI管理器

1.Canvas组件&#xff1a; 注意属性&#xff1a; &#xff08;1&#xff09;渲染模式是&#xff1a;屏幕空间相机 &#xff08;2&#xff09;创建一个UICamera节点&#xff0c;管理相机 &#xff08;3&#xff09;屏幕画布缩放模式 &#xff08;4&#xff09;画布下挂载两…

python使用贪心算法求最大整数问题

对于使用贪心算法的一个比较经典的问题&#xff0c;主要是为了解决最大整数的拼接问题&#xff0c;如果给定一个列表&#xff0c;这个列表中所包括的是一些非负整数&#xff0c;如果对这些整数进行组合&#xff0c;怎样才能组合出一个最大的整数&#xff0c;这里要注意一个问题…

springboot学生信息管理系统

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1研究背景 随着…

浅析爱泼斯坦事件 —— 弱电控制强电原理

据网络文字与视频资料&#xff0c;爱泼斯坦事件是犹太精英阶层&#xff0c;为了掌控美国国家机器为犹太利益集团服务&#xff0c;而精心设下的一个局。本文先假设这个结论成立&#xff0c;并基于此展开讨论。 我们知道&#xff0c;弱电管理强电是电气工程中的一门专门学问&…

探索未来餐饮:构建创新连锁餐饮系统的技术之旅

随着数字化时代的发展&#xff0c;连锁餐饮系统的设计和开发不再仅仅关乎订单处理&#xff0c;更是一场充满技术创新的冒险。在本文中&#xff0c;我们将深入研究连锁餐饮系统的技术实现&#xff0c;带你探索未来餐饮业的数字化美食之旅。 1. 构建强大的后端服务 在设计连锁…

P5461 赦免战俘题解

题目 现有2n2n(n≤10) 名作弊者站成一个正方形方阵等候kkksc03的发落。kkksc03决定赦免一些作弊者。他将正方形矩阵均分为4个更小的正方形矩阵&#xff0c;每个更小的矩阵的边长是原矩阵的一半。其中左上角那一个矩阵的所有作弊者都将得到赦免&#xff0c;剩下3个小矩阵中&…