【数据分析案例】深度分析超市零售商店数据--Python数据分析实战

news2025/2/1 19:49:54

前言

咳咳,又是好久不见~这不高考已经结束了
对python感兴趣的准大学生们,是打算好好玩几个月还是,继续研究学习python呢~ 🤨

请添加图片描述

我呢 还是建议大家劳逸结合哈哈 先玩再学习~ 当然啦 最重要的还是看你们自己呀

不过我以上这些都不能影响我今天发文章

之前都是一些爬虫案例,今天就来一起看看关于数据分析的!

请添加图片描述
有需要代码的 可以看文末名片噢
不要忘记备注啦~

一、项目背景

通过"扫描"零售商店电子销售点个别产品的条形码而获得的消费品销售的详细数据。这些数据提供了有关所售商品的数量、特征和价值以及价格的详细信息。

二、数据来源

【链接】

三、提出问题

  • 消费情况分析及用户购买模式分析
  • RFM和CLV分析
  • 不同类别商品关联规则挖掘

四、理解数据

Date:购买日期
Customer_ID:用户ID
Transaction_ID:交易ID
SKU_Category:商品分类SKU编码
SKU:商品唯一SKU编码
Quantity:购买数量
Sales_Amount:购买金额

五、数据清洗

1.导入数据

需要源码点击文末名片

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline
# 更改设计风格
plt.style.use('ggplot')
plt.rcParams['font.sans-serif'] = ['SimHei']

np.__version__

pd.__version__

df = pd.read_csv('scanner_data.csv')
df.head()

df.info()

2.选择子集

第一列为数据编号,已有索引故删除


df.drop(columns='Unnamed: 0', inplace=True)
df.info()

3.删除重复值

df.duplicated().sum()

数据无重复值

4.缺失值处理

df.isnull().sum()

数据无缺失值

5.标准化处理

df.dtypes


Date为对象类型,需要标准化为日期类型格式


df.Date = pd.to_datetime(df.Date, format='%d/%m/%Y')
df.dtypes

6.异常值处理

df[['Quantity','Sales_Amount']].describe()

购买数量存在小于1是由于称重单位不足1所致,非异常值

六、分析内容

1.消费情况按月分析

(1)每月消费总金额趋势分析

df['Month'] = df.Date.astype('datetime64[M]')
df.head()


grouped_month = df.groupby('Month')


grouped_month.Sales_Amount.sum()


20181月数据可能统计不全,不纳入趋势分析


grouped_month.Sales_Amount.sum().head(12).plot()

由上图可知:消费金额波动较大,其中第一季度保持持续上升,后续波动较大,整体呈上升趋势
(2)每月交易次数趋势分析

grouped_month.Transaction_ID.nunique().head(12).plot()

由上图可知:交易次数波动较大,前期呈上升趋势,五月之后交易次数开始下降,在八月降至最低值,后续开始波动回升,在十二月份重回峰值

(3)每月商品购买数量趋势分析

grouped_month.Quantity.sum().head(12).plot()

由上图可知:商品购买数量波动较大,整体趋势同交易次数保持一致

(4)每月消费人数趋势分析

grouped_month.Customer_ID.nunique().head(12).plot()

由上图可知:每月购买人数可分简单为三个阶段,1-5月呈持续上升趋势,6—8呈持续下降趋势,9-12月呈波动上升趋势

2.用户分布分析

(1)新用户分布

grouped_customer = df.groupby('Customer_ID')
grouped_customer.Date.min().value_counts().plot()

由上图可知:新用户获取不稳定,波动较大,整体有略微下降趋势

grouped_customer.Month.min().value_counts().plot()

由上图可知:按月统计,每月新用户用户数有明显下降趋势。说明新用户获取呈大幅下降趋势,需要引起注意,适当增加营销活动提升新用户的获取

(2)一次消费及多次消费用户占比分析

#仅消费一次用户占比

(grouped_customer.Transaction_ID.nunique() == 1).sum()/df.Customer_ID.nunique()

由计算得:存在一半的用户只进行了一次消费

grouped_month_customer = df.groupby(['Month', 'Customer_ID'])


#每个用户每月的第一次购买时间
data_month_min_date = grouped_month_customer.Date.min().reset_index()
#每个用户的第一次购买时间
data_min_date = grouped_customer.Date.min().reset_index()


#通过Customer_ID联立两表
merged_date = pd.merge(data_month_min_date, data_min_date, on='Customer_ID')
merged_date.head()


#Date_x等于Date_y则为每月新用户
((merged_date.query('Date_x == Date_y')).groupby('Month').Customer_ID.count() / merged_date.groupby('Month').Customer_ID.count()).plot()

由上图可知:每月新用户占比整体呈下降趋势,结合每月消费人数趋势可知,第四季度消费人数有上升趋势,故期间复购人数有所提升

3.用户分层分析

(1)RFM分层分析

pivot_rfm = df.pivot_table(index='Customer_ID',
              values=['Date', 'Transaction_ID', 'Sales_Amount'],
              aggfunc={'Date':'max', 'Transaction_ID':'nunique', 'Sales_Amount':'sum'})


pivot_rfm['R'] = (pivot_rfm.Date.max() - pivot_rfm.Date)/np.timedelta64(1, 'D')
pivot_rfm.rename(columns={'Transaction_ID':'F', 'Sales_Amount':'M'}, inplace=True)


def label_func(data):
    label = data.apply(lambda x:'1' if x > 0 else '0')
    label = label.R + label.F + label.M
    labels = {
        '111':'重要价值客户',
        '011':'重要保持客户',
        '101':'重要发展客户',
        '001':'重要挽留客户',
        '110':'一般价值客户',
        '010':'一般保持客户',
        '100':'一般发展客户',
        '000':'一般挽留客户'
    }
    return labels[label]
pivot_rfm['label'] = pivot_rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(label_func, axis=1)


pivot_rfm.label.value_counts().plot.barh()

pivot_rfm.groupby('label').M.sum().plot.pie(figsize=(6,6), autopct='%3.2f%%')

pivot_rfm.groupby('label').agg(['sum', 'count'])

由上表及图可知:

销售额主要来源重要保持客户,人数占比最高的为一般发展客户
重要保持客户:销售额的主要来源,近期有消费,且消费高,消费频率不足,可以适当举行营销活动,提升此层客户的购买频率
重要价值客户:销售额的第二来源,近期有消费,消费高,频率高,尽可能使该层客户保持现状
重要发展客户:消费以及消费频次高,近期没有消费,可以使用适当策略召回用户,参与消费
重要挽留客户:消费高,但频次低且近期未消费,处在流失的边缘,可以通过适当活动,使其参与到消费中来,防止流失
一般价值客户:消费低,消费频率高且近期有消费,可以使用优惠券等形式活动刺激该层客户的消费,提升其消费额
一般发展客户:人数占比最高,近期有消费,但消费额以及消费频次不高,考虑到人数占比高,可以适当举办活动提升消费频次和消费额
一般保持客户:在成本与资源控制下,酌情考虑
一般挽留客户:在成本与资源控制下,酌情考虑

(2)用户状态分层分析

pivoted_status = df.pivot_table(index='Customer_ID', columns='Month', values='Date', aggfunc='count').fillna(0)

def active_status(data):
    status = []
    for i in range(len(data)):     
        #若本月没有消费
        if data[i] == 0:
            if len(status) > 0:
                if status[i-1] == 'unreg':
                    status.append('unreg')
                else:
                    status.append('unactive')
            else:
                status.append('unreg')
        #若本月有消费
        else:
            if len(status) > 0:
                if status[i-1] == 'unreg':
                    status.append('new')
                elif status[i-1] == 'unactive':
                    status.append('return')
                else:
                    status.append('active')
            else:
                status.append('new')
    status = pd.Series(status, index = data.index)
    return status

active_status = pivoted_status.apply(active_status, axis=1)

active_status.replace('unreg', np.nan).apply(lambda x:x.value_counts()).fillna(0).T.apply(lambda x: x/x.sum(),axis=1).plot.area()

由上图可知:

新用户:新用户占比呈明显下降趋势,说明拉新运营不足
活跃用户:在二月占比达到最高,后续呈缓慢下降趋势,说明消费运营正在下滑
不活跃用户:不活跃用户呈明显上升趋势,客户流失较为明显
回流客户:有缓慢上升趋势,说明召回运营不错

4.用户生命周期分析

(1)用户生命周期分布

#构成用户生命周期研究的数据样本需要消费次数>=2次的用户
clv = (grouped_customer[['Sales_Amount']].sum())[grouped_customer.Transaction_ID.nunique() > 1]


clv['lifetime'] = (grouped_customer.Date.max() - grouped_customer.Date.min())/np.timedelta64(1,'D')


clv.describe()

- 由上表可知:消费一次以上的用户平均生命周期为116天,用户生命周期内平均消费金额为121.47元

clv['lifetime'].plot.hist(bins = 50)

由上图可知:

生命周期在0-90天内的用户较多,说明生命周期短的客户占比较高,90天内流失率较高,此部分用户可以作为运营重点,延长这些用户的生命周期;
生命周期在90-250之间的分布较为均匀,这也是大多数用户的生命周期,可以刺激这些用户的消费,使其在生命周期内提升消费金额;
生命周期大于250天的人数极少,说明生命周期较长的忠诚客户占比不高。
(2)用户生命周期价值分布

clv['Sales_Amount'].plot.hist(bins = 50)

由上图可知:

绝大部分用户生命周期内价值在500以内,且其中大部分在100以内,存在较大极值拉高均值,数据向右偏斜。
(3)用户生命周期及其价值相关关系

plt.scatter(x='lifetime', y='Sales_Amount', data=clv)

由上图可知:

用户生命周期与其期间客户价值不存在线性关系,当生命周期在300天内,部分生命周期较长用户贡献的价值高于生命周期较短的用户;
当生命周期大于300天,存在部分用户贡献价值较少,由于数据量不足等原因,结果仅供参考

5.回购率与复购率分析

(1)复购率分析

grouped_month_customer

customer_month_again = grouped_month_customer.nunique()
customer_month_again

#每月消费次数大于1的用户数
customer_month_again = grouped_month_customer.nunique().query('Transaction_ID > 1').reset_index().groupby('Month').count().Customer_ID
# customer_month_again
#每月消费用户数
customer_month = grouped_month.Customer_ID.nunique()
# #每月复购率
(customer_month_again/customer_month).plot()
customer_month
(customer_month_again/customer_month)

由上图可知:复购率在25%上下浮动,说明每月有25%的用户会进行多次消费;前三个月的复购率有所下降,后续有所回升,整体有上升趋势,应结合本身商务模式,决定进一步提升复购率还是注重新用户的获取。最后一月由于数据量不足,结果以真实数据为主。

(2)回购率分析

#  1表示前90天消费且本月回购  0表示前90天消费本月未回购  nan表示前90天未消费
def buy_back(data):
    status = [np.nan,np.nan,np.nan]
    for i in range(3,len(data)):
        #本月购买
        if data[i] == 1:
            #前90天购买
            if (data[i-1] == 1 or data[i-2] ==1 or data[i-3] == 1):
                status.append(1)
            #前90天未购买
            else:
                status.append(np.nan)
        #本月未购买
        else:
            #前90天购买
            if (data[i-1] == 1 or data[i-2] ==1 or data[i-3] == 1):
                status.append(0)
            #前90天未购买
            else:
                status.append(np.nan)
    status = pd.Series(status, index = data.index)
    return status

back_status = pivoted_status.apply(buy_back, axis=1)
back_status.head()

(back_status.sum()/back_status.count()).plot()

由上图可知:90天内回购率,即90天内重复购买率在10%以下,说明目前商店处于用户获取模式,然而由前面分析可知,新用户获取呈下降趋势,目前商店并不健康,当前阶段应当将重心放在新用户获取上,

6.商品关联规则挖掘

(1)分析热销商品

#取出销量排名前10的商品类型
hot_category = df.groupby('SKU_Category').count().Sales_Amount.sort_values(ascending=False)[:10].reset_index()
plt.barh(hot_category.SKU_Category, hot_category.Sales_Amount)

#热销商品占比
hot_category['percent'] = hot_category.Sales_Amount.apply(lambda x:x/hot_category.Sales_Amount.sum())
plt.figure(figsize=(6,6))
plt.pie(hot_category.percent,labels=hot_category.SKU_Category,autopct='%1.2f%%')
plt.show()

category_list = df.groupby('Transaction_ID').SKU_Category.apply(list).values.tolist()

from apyori import apriori

min_support_value = 0.02
min_confidence_value = 0.3
result = list(apriori(transactions=category_list, min_support=min_support_value, min_confidence=min_confidence_value, min_left=0))

result

由上结果可得:

  • ‘FU5’–>‘LPF’:支持度为约2.1%,置信度约为49.5%。说明同时购买这两类商品发生的可能性为约2.1%,先购买FU5类型产品后,同时购买LPF类型产品的概率为49.5%
  • ‘IEV’–>‘LPF’:支持度约为3.1%,置信度约为48.9%。说明同时购买这两类商品发生的可能性约为3.1%,先购买IEV类型产品后,同时购买LPF类型产品的概率约为48.9%
  • ‘LPF’–>‘IEV’:支持度约为3.1%,置信度约为43.3%。说明同时购买这两类商品发生的可能性约为3.1%,先购买LPF类型产品后,同时购买IEV类型产品的概率约为43.3%
  • ‘OXH’–>‘LPF’:支持度约为2.0%,置信度约为48.1%。说明同时购买这两类商品发生的可能性约为2.0%,先购买IEV类型产品后,同时购买LPF类型产品的概率约为48.1%

最后

就是这样 终于结束了 需要代码的 可以点击文末名片获取噢

请添加图片描述

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

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

相关文章

[NOI2007] 调兵遣将

题目描述 我军截获的情报显示,敌军正在集结兵力试图向我军重要的军械研究所发起进攻。由于我军正处于多线作战的状态,无法抽调大批兵力前去支援,指挥部决定通过有效的战前部署来提高胜率,减少伤亡和损失。 该军械研究所的平面图…

网络安全自学笔记+学习路线+就业规划(超详细)

每天都有新闻报道描述着新技术对人们的生活和工作方式带来的巨大乃至压倒性影响。与此同时有关网络攻击和数据泄露的头条新闻也是日益频繁。 攻击者可谓无处不在:企业外部充斥着黑客、有组织的犯罪团体以及民族国家网络间谍,他们的能力和蛮横程度正日渐…

如何使虚拟机自动生成ip地址

一. 打开虚拟机并登录账号进入命令行界面输入指令: vi /etc/sysconfig/network-scripts/ifcfg-ens33 通过指令进入到下面的界面当中 点击键盘输入 "i" 进入编辑模式将文件修改为 文件当中的 BOOTPROTO可以将ip地址定义为自动生成类型或者静态指定类型其中…

力扣 213. 打家劫舍 II

一、题目描述 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻…

高考后计算机人工智能大类专业的选择建议

随着GPT的出现,很多人开始质疑是否还需要学计算机专业,计算机专业是否会消失。 先给结论,不会! 只是会产生分层,大体上是这样的: 核心代码部分还是需要人来写的,只要是代码方式出现的结果&#…

了解ASEMI代理英飞凌TLE6208-6G其功能和应用的综合指南

编辑-Z TLE6208-6G是一款高度集成、通用且高效的汽车半桥驱动器,由英飞凌设计。这种功能强大的设备专门设计用于满足汽车应用的苛刻要求,如控制直流电机、螺线管和电阻负载。在本文中,我们将深入研究TLE6208-6G的功能、优点和应用&#xff0…

【Spring MVC】这几种传参方式这么强大,让我爱不释手,赶快与我一起去领略吧 ! ! !

前言: 大家好,我是良辰丫,在上2一篇文章中我们已经初步认识了Spring MVC,并且学习了热部署的配置,今天我们将继续开始我们的Spring MVC的学习! ! !💌💌💌 🧑个人主页:良辰针不戳 📖所属专栏:jav…

JDK9~17+Springboot3 @Resource常见问题和解决方案

一、常见问题描述 因为JDK版本升级的改动,在Jdk9~17环境下,搭建Springboot项目,会出现原有Resource(javax.annotation.Resource)不存在的问题,导致项目从Jdk8迁移到高版本时遇到的问题 原因 你可能会问&…

TiDB亿级数据亚秒响应查询将MySql数据全量迁移到TiDB

目录 1 下载安装TiDB工具包1.1 检查最新版本1.2 下载tidb-toolkit 2 Dumpling导出数据2.1 Dumpling工具简介2.2 导出需要的权限2.3 创建用户并授权2.4 验证数据库2.5 导出sql文件2.6 查看导出文件 3 TiDB Lightning导入数据3.1 TiDB Lightning简介3.2 TiDB Lightning 整体架构3…

蓝桥杯【第14届国赛】Python B组

本题解仅代表个人观点,仅供参考,欢迎各位指正 A:弹珠堆放 【问题描述】 小蓝有 20230610 颗磁力弹珠,他对金字塔形状尤其感兴趣,如下图所示: 高度为 1 的金字塔需要 1 颗弹珠; 高度为 2 的金字…

【Jetpack】使用 Room 中的 Migration 升级数据库异常处理 ( 多个数据库版本的迁移 | fallbackToDestructiveMigration() 函数处理升级异常 )

文章目录 一、Room#Migration 迁移工具升级数据库二、多个数据库版本的迁移三、数据库异常处理 - RoomDatabase.Builder#fallbackToDestructiveMigration() 函数四、完整代码示例 一、Room#Migration 迁移工具升级数据库 Room Migration 数据库迁移工具 是 Android Jetpack Arc…

【AI实战营第二期】第三次作业——基于 RTMDet 的气球检测(包含数据集)

作业:基于 RTMDet 的气球检测 背景:熟悉目标检测和 MMDetection 常用自定义流程。 任务: 基于提供的 notebook,将 cat 数据集换成气球数据集; 按照视频中 notebook 步骤,可视化数据集和标签; 使用MMDetection算法库…

01_Linux字符设备驱动开发

目录 字符设备驱动简介 驱动模块的加载和卸载 字符设备注册与注销 实现设备的具体操作函数 添加LICENSE和作者信息 Linux设备号的组成 设备号的分配 chrdevbase字符设备驱动开发实验 创建VSCode工程 添加头文件路径 编写实验程序 C库文件操作基本函数 编写测试APP…

苹果Vision Pro正式发布,下一个iPhone诞生了?

在库克即将退休之际,苹果开启了下一个十年。 2023年6月6日,在苹果WWDC开发者大会上,苹果发布了15寸的MacBook Air,以及一众iOS 17、iPad OS 17、Mac OS等系统的更新。当我们觉得这些常规更新有点不痛不痒,甚至想大呼“…

​selenium中元素定位正确但是操作失败,6种解决办法全稿定

selenium中元素定位正确但是操作失败的原因无外乎以下4种: 一、页面没加载好 解决方法:添加等待方法,如: time.sleep() 二、页面提交需要等待给数据后台 解决方法:添加等待方法,如: time.sl…

一套完整的三甲医院医学影像科PACS系统源码

一、PACS系统概述: 基于VC MSSQL开发的一套三甲医院医学影像PACS系统源码,集成3D影像后处理技术和功能,包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等能满足影像科功能。 二、PAC…

C/C++ 作用域,生命周期,执行线程的概念

相互影响 在C中,对象的生命周期、作用域和执行线程是三个相互关联但又相对独立的概念。它们共同决定了对象在程序中的行为和状态。下面我将详细解释这三个概念以及它们之间的关系和互相影响。 生命周期:对象的生命周期是指从对象被创建(构造…

Python暑假自律打卡学习班,免费,速来(2)

小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生。 和猫妹学Python,一起趣味学编程。 很快就放暑假了,还有20多天吧! 猫妹对这个暑假相当期待啊, 想想今年的五一劳动节有多火爆…

仙境传说RO:npc汉化方法

仙境传说RO:npc汉化方法 大家好我是艾西,在我们说了那么多期的教程中大家应该有发现游戏内很多都还是英文的,如果对于国内的玩家开展这个游戏可能有些不熟悉的小伙伴玩起来会有点难受,今天艾西跟大家分享下怎么汉化NPC等。 我们…

异常数据检测 | Python实现基于高斯概分布的异常数据检测

文章目录 文章概述模型描述源码分享学习小结参考资料文章概述 高斯分布也称为正态分布。它可以被用来进行异常值检测,不过我们首先要假设我们的数据是正态分布的。不过这个假设不能适应于所有数据集。但如果我们做了这种假设那么它将会有一种有效的方法来发现异常值。 模型描述…