【促销定价】背后的算法技术 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)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python -- pyQt5中 样式设置

一、父控件设置样式表后对子控件产生影响&#xff0c;控制styleSheet的作用范围 https://blog.csdn.net/qq_31073871/article/details/90288625 QFrame 作为容器&#xff0c;放入其他多种部件&#xff0c;里面的边框都生效 在类名后面用 #号串接变量名&#xff0c;子控件不…

Required request parameter ‘ids‘ for method parameter type List is not present]

在写delete方法的时候&#xff0c;出现了bug 于是将RequestParam换成PathVariable 两者有何区别&#xff1f; pathVariable和RequestParam的区别 在Spring MVC框架中&#xff0c;PathVariable 和 RequestParam 是两种用于从HTTP请求中获取参数的注解&#xff0c;它们的区别…

决策树:理解机器学习中的关键算法

决策树&#xff1a;理解机器学习中的关键算法 决策树是一种流行而强大的机器学习算法&#xff0c;它从数据中学习并模拟决策过程&#xff0c;以便对新的未知数据做出预测。由于其直观性和易理解性&#xff0c;决策树成为了分类和回归任务中的首选算法之一。在本文中&#xff0…

2024最新外贸建站:SiteGround主机购买使用及自建外贸独立站教程

原文来源&#xff1a;https://guomuyu.com/building-website-siteground.html 在开始之前&#xff0c;让我们先了解一下什么是外贸独立站。外贸独立站简单来说就是一个拥有独立域名的网站&#xff0c;它不依赖于第三方平台&#xff08;如阿里巴巴、亚马逊等&#xff09;的网站…

Python--闭包

在 Python 中&#xff0c;闭包是一种函数&#xff0c;它能够记住并访问其所在词法作用域&#xff08;即定义该函数的作用域&#xff09;中的变量&#xff0c;即使该函数在其词法作用域之外被调用。要形成闭包&#xff0c;需要满足以下几个条件&#xff1a; 必须有一个内嵌函数&…

网页设计与网站建设作业html+css+js,一个简易的游戏官网网页

一个简易的游戏网页 浏览器查看 目录结构 部分代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport&…

重学Java 5 idea详细使用和运算符

慢点跑&#xff0c;前面的路不好走 ——24.1.14 一、IDEA的使用 1.idea的介绍 1.概述&#xff1a;开发工具 2.特点&#xff1a; a、idea是java写的&#xff0c;所以本地上必须有正确的jdk环境 b、idea自动保存 c、不用我们打开dos命令窗口执行javac和java命令 d、idea有强大的…

Mnajora 使用deb包安装软件

说明 Mnajora 安装deb软件包主要有两种方式 可以使用dpkg 直接安装也可是使用debtap将deb软件包转换成 使用dpkg sudo pacman -S dpkg #安装dpkgsudo dpkg -i ###.deb #使用dpkg安装deb软件包和在ubuntu上是一样的 安装成功 使用debtap debtap是一个用于将.deb包转换为A…

第 2 课 ROS 系统安装和环境搭建

文章目录 方法一&#xff1a;一键安装&#xff08;推荐&#xff09;方法二&#xff1a;逐步安装&#xff08;常规安装方式&#xff09;1.版本选择2.检查 Ubuntu 的软件和更新源3.设置 ROS 的下载源3.1 设置国内下载源3.2 设置公匙3.3 更新软件包 4. 安装 ROS5. 设置环境变量6. …

鸿蒙Harmony-PersistentStorage--持久化存储UI状态储详解

用简单的心境&#xff0c;对待复杂的人生&#xff0c;方能看淡得失&#xff0c;从容入世&#xff0c;潇洒自如&#xff0c;心变得简单了&#xff0c;世界也就简单了 目录 一&#xff0c;定义 二&#xff0c;限制条件 三&#xff0c;使用 一&#xff0c;定义 LocalStorage和App…

midjournery教程(可以在微信中免费使用)

图片比例 9:16 --ar 9:16 图片风格化 --s 1000 --stylize 1000 版本 Midjourney 定期发布新模型版本以提高效率、一致性和质量。默认为最新型号&#xff0c;但可以使用--version或--v参数或使用/settings命令并选择型号版本来使用其他型号。不同的模型擅长处理不同类型的图…

爬虫-6-数据提取-beautifulsoup4

#声明:本文仅供学习。 (●—●)

12.3在应用层使用SPI总线

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

“华为杯“第四届中国研究生数学建模竞赛-D题:邮路规划与邮车调度

目录 摘 要&#xff1a; 1.问题的重述 2.模型的假设与符号说明 2.1 针对本问题&#xff0c;本文做出如下假设 2.2 符号说明 3.问题的数学模型 4.问题的求解 4.1 问题一的求解 4.1.1 最少邮车数的求法 4.1.2 邮路规划及路径选择 4.1.3 问题的求解结果 4.2 问题二的求…

隧道应用3-Cobalt Strike正反向连接多层内网

Cobalt Strike 正向连接多层内网&#xff1a; teamserver 不允许访问 B &#xff0c;但是服务器上A有权限&#xff08; A 与 B 在同一网段&#xff09;&#xff0c;若 A 服务上已经有了 cs 的后门&#xff0c;则可以通过 cs 的正向连接去连接 B &#xff0c;在 teamserver 通…

datavrap可视化设计器使用手册

datavrap使用手册 一、产品简介 datavrap是一个动态数据可视化设计器&#xff0c;通过简单配置生成可视化视频&#xff0c;图片和gif。 站长&#xff1a;B站UP&#xff0c;夹克mnnm 这个产品的灵感是在做B站视频时&#xff0c;觉得每次通过修改代码录屏实现视频制作太过于繁琐&…

基于Matlab/Simulink的MIL仿真验证解决方案

文章目录 需求追溯 虚拟环境 模型检查 仿真验证 测试报告 参考文献 针对模型开发阶段的ECU算法&#xff0c;可以很直接地将其与虚拟车辆模型连接起来&#xff0c;通过MIL对其进行验证和确认。可以在开发过程的早期检测到设计错误和不正确的需求&#xff0c;也有助于安全地…

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

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

SouthernBiotech抗荧光淬灭封片剂

荧光淬灭又称荧光熄灭或萃灭&#xff0c;是指导致特定物质的荧光强度和寿命减少的所有现象。引起荧光淬灭的物质称为荧光淬灭剂。SouthernBiotech专门开发的Fluoromount-G系列荧光封片剂是以甘油为基础&#xff0c;加入抗荧光淬灭剂&#xff0c;可明显降低荧光淬灭现象&#xf…

天津python培训学校 Python有怎样的前景?

很多人以为Python之所以变得火热的原因是人工智能和大数据的兴起&#xff0c;这并非是全部的原因&#xff0c;Python是一门很适合人工智能领域的编程语言&#xff0c;人工智能目前虽然还处于前期阶段&#xff0c;但是对人工智能方面的人才确在不断增加&#xff0c;能够提供的岗…