数据分析项目-英国礼品商城数据分析
Kaggle: UK E-Commerce 用户行为分析
项目概览
数据背景:
此次项目数据来自Kaggle,是英国零售商的实际交易数据,包含了2010年12月1日至2011年12月9日在英国注册的非实体网上零售发生的所有交易。公司主要销售独特的全天候礼品。该公司的许多客户都是批发商。分析目的:
采用RFM模型,从用户、地区和时间等维度分析用户行为并提出优化建议。
理解数据
将下载好的数据导入数据库中,得到一个542K x 8 的数据集,列属性分别为:
- InvoiceNo --> 订单号码: 6位字符串
- StockCode --> 产品代码: 6位字符串
- Description --> 产品描述
- Quantity --> 产品数量:交易产品数量
- InvoiceDate --> 订单日期:订单发生的日期和时间
- UnitPrice --> 单价:浮点数值
- CustomerID --> 顾客ID:5位字符串
- Country --> 国家:客户所在地
数据预处理
观察数据集
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 541909 entries, 0 to 541908
Data columns (total 8 columns):
InvoiceNo 541909 non-null object
StockCode 541909 non-null object
Description 540455 non-null object
Quantity 541909 non-null int64
InvoiceDate 541909 non-null object
UnitPrice 541909 non-null float64
CustomerID 406829 non-null float64
Country 541909 non-null object
dtypes: float64(2), int64(1), object(5)
memory usage: 33.1+ MB
df.head()
df.describe()
修改一下 InvoiceDate 的日期显示类型,然后先增加一列日期
df['InvoiceDate']=pd.to_datetime(df.InvoiceDate,format='%m/%d/%Y %H:%M')
df['Date']=df['InvoiceDate'].dt.date
检查,处理空值
检查空值
df.isnull().sum()
显示空值行
df[df.isnull().T.any()]
统计不同列的缺失率
描述和客户ID有缺失,而且确实的比例比较高。
df.apply(lambda x :sum(x.isnull())/len(x),axis=0)
删除不用的数据
df.drop(['Description'],axis=1,inplace=True)
df.head()
标记缺失值
df['CustomerID'] = df['CustomerID'].fillna('U')
新增加一列用以表示每笔订单的金额
df['amount'] = df['Quantity']*df['UnitPrice']
df.head()
去重
df = df.drop_duplicates()
再看一下UnitPrice小于0的情况,即退款的订单
df2=df[df['UnitPrice']<=0]
df2.shape[0]/df.shape[0]
再看一下有效订单,这里排除了金额小于等于0的订单,即退货情况和赠品(我认为单价为0应该是赠品吧)
df1=df[(df['Quantity']>0) & (df['UnitPrice']>0)]
df1
RFM模型分析
DATE一列已经被创造出来,且我们保存了原来的InvoiceDate 方便之后进行对照,RFM的定义不再赘述,下面是针对该实验的每个参数的实现方法:
R:最近的一次的消费。我们采用最后一天(max)作为“今天”减去每位顾客最后一次消费的时间
F: 每位顾客购买的频次
M:每位顾客购买的销量总额: unitprice*quantity
R_value=df1.groupby('CustomerID')['Date'].max()
R_value
R_value = (df1['Date'].max() - R_value).dt.days
R_value
F_value = df1.groupby('CustomerID')['InvoiceNo'].nunique()
F_value
M_value = df1.groupby('CustomerID')['amount'].sum()
M_value
R_value.describe()
sns.set(style = 'darkgrid')
plt.hist(R_value,bins=30)
plt.show()
M_value.describe()
plt.hist(M_value,bins=30)
plt.show()
plt.hist(M_value[M_value<2000],bins=40)
plt.show()
F_value.describe()
F_value.quantile([0.1,0.2,0.3,0.4,0.5,0.9,1])
plt.hist(F_value,bins=30)
plt.show()
plt.hist(F_value[F_value<30],bins=30)
plt.show()
R_bins = [0,30,90,180,360,720]
F_bins = [1,2,5,10,20,5000]
M_bins = [0,500,2000,5000,10000,200000]
R_score = pd.cut(R_value,R_bins,labels=[5,4,3,2,1],right=False)
R_score
F_score = pd.cut(F_value,F_bins,labels=[1,2,3,4,5],right=False)
F_score
M_score = pd.cut(M_value,M_bins,labels=[1,2,3,4,5],right=False)
M_score
rfm = pd.concat([R_score,F_score,M_score],axis=1)
rfm.rename(columns={'Date':'R_score','InvoiceNo':'F_score','amount':'M_score'},inplace=True)
rfm
rfm.info()
for i in ['R_score','F_score','M_score']:rfm[i]=rfm[i].astype(float)
rfm.describe()
rfm['R'] = np.where(rfm['R_score']>3.82,'高','低')
rfm['F'] = np.where(rfm['F_score']>2.03,'高','低')
rfm['M'] = np.where(rfm['M_score']>1.89,'高','低')
rfm
def trans_value(x):if x=='高高高':return '高价值客户'elif x=='高低高':return '重点发展客户'elif x=='低高高':return '重点保持客户'elif x=='低低高':return '重点挽留客户'elif x=='高高低':return '一般价值客户'elif x=='高低低':return '一般发展客户'elif x=='低高低':return '一般保持客户'else:return '潜在客户'
rfm['用户等级']=rfm['value'].apply(trans_value)
rfm
重要价值客户(111):最近消费时间近、消费频次和消费金额都很高,VIP中P
重要保持客户(011):最近消费时间较远,但消费频次和金额都很高,说明这是个一段时间没来的忠实客户,我们需要主动和他保持联系,需要精准推送。
重要发展客户(101):最近消费时间较近、消费金额高,但频次不高,忠诚度不高,很有潜力的用户,应该重点发展比如让他成为会员来保持联系。
重要挽留客户(001):最近消费时间较远、消费频次不高,但消费金额高的用户,可能是将要流失或者已经要流失的用户,应当实施挽留措施
rfm['用户等级'].value_counts()
从总体上看,R_score的表现总体较好,但是用户消费频次和消费金额mean值偏低(由下图可见,超过90%的用户消费频次和消费在3分以内)
**猜想:**可能是是由这家网站销售的物品特性所决定的,因为购买礼品对于个人来说时间比较固定,一般是过节前后或者是值得纪念的日子,即购买的时间不同的客户应该有一定重合且比较固定。除此之外,高价礼品的比例也比较小,符合日常人与人之间送礼品的规律,值得注意的是,超过60%的用户在90天内购买过礼物。
数据探索
将日期和时间拆分成不同的特征,便于后面探索销售情况于时间的关系。
data["Total"]=data["Quantity"]*data["UnitPrice"]
data[["Date","Time"]]=data["InvoiceDate"].str.split(" ",expand=True)
data[["Month","Day","Year"]] = data["Date"].str.split("/",expand=True)
data["Hour"]=data["Time"].str.split(":",expand=True)[0].astype("int")
data_buy = data[data["Quantity"] >= 0]
data_return = data[data["Quantity"] < 0]
data.head()
看看哪些产品是卖的多的,哪些产品退货多的?
product_quantity=data["Quantity"].groupby(data["StockCode"]).sum().sort_values(ascending=False)
看一看产品价格情况
商品的平均价格是6.9,但是方差特别大,而且中位数是2.5,说明是一个右偏分布,大部分商品还是低价格的,也符合前面的猜想
data_unique_stock=data.drop_duplicates(["StockCode"])
data_unique_stock["UnitPrice"].describe()
商品价格的累计分布
price_bin=pd.cut(data_unique_stock["UnitPrice"],bins=[0,1,2,3,4,5,6,7,10,15,20,25,30,100,10000,20000,30000,40000]).value_counts().sort_index()
price_per=price_bin/price_bin.sum()
price_per
商品价格在10元以内的占了93.28%,在100元以内的占了99.79%。
price_cumper=price_bin.cumsum()/price_bin.sum()
price_cumper
不同价格的销售数量比较
71.68%的商品销量集中在价格在2元以内的商品;99.7%的商品销量集中的价格在15元以内的商品
cut=pd.cut(data["UnitPrice"],bins=[0,1,2,3,4,5,6,7,10,15,20,25,30,100,10000,20000,30000,40000])
quantity_price=data["Quantity"].groupby(cut).sum()
quantity_price.cumsum()/quantity_price.sum()
退货商品的价格分布与退货量情况退货商品的价格分布与退货量情况
退货商品最多的价格区间是(1,2]元,退货商品价格在10元以内的占了95.46%。
data_return_unique_stock=data_return.drop_duplicates("StockCode")
return_cut=pd.cut(data_return_unique_stock["UnitPrice"],bins=[0,1,2,3,4,5,10,15,20,50,100,200,500,1000]).value_counts().sort_index()
pd.concat([return_cut/return_cut.sum(),return_cut.cumsum()/return_cut.sum()],axis=1)
(return_cut/return_cut.sum()).plot()
(price_bin/price_bin.sum()).plot()
蓝色是退货商品的价格分布,红色是全部商品的价格分布。从退货商品种类的角度,退货商品与总体商品相比,更集中在0-3元与5-10元这两个区间
顾客维度的分析
customer_total=data_buy["Total"].groupby(data_buy["CustomerID"]).sum().sort_values(ascending=False)
customer_total[:20]
customer_buy_fre=data_buy.drop_duplicates(["InvoiceNo"])["InvoiceNo"].groupby(data_buy["CustomerID"]).count().sort_values(ascending=False)
customer_buy_fre[:20]
customer_total.drop("nan",inplace=True)
customer_buy_fre.drop("nan",inplace=True)
plt.scatter(customer_buy_fre.sort_index(),customer_total.sort_index())
plt.axhline(y=50000,c="green")
plt.axvline(x=50,c="blue")
根据顾客购买次数和购买金额,对顾客进行分组,采取不同的营销措施。
:订单的商品种类分布
未退货的顾客中,大部分的订单商品种类在100以内
order_type=data_buy["StockCode"].groupby(data_buy["InvoiceNo"]).count().sort_values(ascending=False)
pd.cut(order_type,bins=[0,50,100,150,200,250,300,500,1000,1200]).value_counts()
退货顾客的商品种类大部分都在10以内
order_type_r=data_return["StockCode"].groupby(data_return["InvoiceNo"]).count().sort_values(ascending=False)
pd.cut(order_type_r,bins=[0,10,20,30,40,50,60,150]).value_counts()
哪些国家的顾客消费占比最大?哪些国家的顾客数量最多?哪些国家的顾客平均消费最高?
country_total = data["Total"].groupby(data["Country"]).sum().sort_values(ascending=False)
country_customer=data["CustomerID"].groupby(data["Country"]).count().sort_values(ascending=False)
country_total_percent=(country_total/country_total.sum())
country_total_percent
country_customer_percent=country_customer/country_customer.sum()
country_customer_percent
data["Total"].groupby(data["Country"]).mean().sort_values(ascending=False)
不同月份的销售金额情况?订单情况?
data["Total"].groupby(data["Month"]).sum().sort_index().plot()
data["InvoiceNo"].groupby(data["Month"]).count().sort_index().plot()
- 销量高的货物有哪些,退货多的货物有哪些
- 产品价格分布表明该网站以批发低价产品为主,93%的产品单价在10元以内.产品单价-销量图表明72%的产品销量集中在2元以内的产品,99%的产品销量集中在15元以内的产品。
- 退货产品最多的价格区间是1-2元,与总体相比,退货产品的价格更集中在10元以内
- 全部订单中,大部分成功交易的产品种类在100以内,大部分退货订单的产品种类在10以内
- 该电商网站超过90%的顾客来自英国本土,84%的销售额来自英国本国,说明英国本土是绝对的主要市场,但是同时也说明,英国之外的消费者平均消费能力更强。
- 在一年中,订单金额和订单数量呈波动上升,11月份达到最大值,这主要是因为12月份、1月份有西方的节日,是需要送礼物的日期,而该电商网站的顾客是批发商,提前进货是符合常理的,所以平均订单金额和订单量在9月份达到最大值。
数据分析项目-英国礼品商城数据分析相关推荐
- EXCEL数据分析项目 - 商贸企业销售数据分析实战
目录 一.前提信息 1 案例背景 2 项目目标 3 数据理解 二.总体分析 需求1 分析2020到2021年各类产品销售情况 需求2 分析2021年各地区的销售情况 需求3 2020年 - 202 ...
- 数据分析项目-淘宝用户数据分析
分析思路 1. 分析用户在使用淘宝APP时的行为,确定相关指标,确定用户流失环节. 2. 分析用户在不同时间段的行为趋势变化. 3. 通过对部分商品的用户行为分析,提出针对不同类型用户的调整建议. A ...
- 数据分析项目-合集-day02
数据分析项目-合集-day02 需求: - 导入文件,查看原始数据 - 将人口数据和各州的简称数据进行合并 - 将合并的数据中重复的abbreviation进行删除 - 查看存在缺失数据的列 - 找到 ...
- 让你能进“大厂”的数据分析项目是长怎样?全套路线(建议收藏)
<算法 + 数据结构>全套路线(建议收藏) 前言 所谓活到老,学到老,虽然我感觉自己已经学了很多算法了,但是昨天熬夜整理完以后发现,自己还是个弟弟,实在忍不住了,打算把 算法学习路线 ...
- 让你能进“大厂”的数据分析项目是长怎样的?
微信搜索「Dathon数据分析」关注后,在后台回复「亮眼项目」即可免费获取本文提到的项目技能栈与学习路径. 也可以截图后,微信扫码关注后回复「亮眼项目」 文字版 暂时看不到视频的同学看这里: 一.自我 ...
- (附源码)计算机毕业设计SSM化妆品网上商城数据分析系统
(附源码)计算机毕业设计SSM化妆品网上商城数据分析系统 项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe( ...
- (附源码)SSM化妆品网上商城数据分析系统JAVA计算机毕业设计项目
项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclis ...
- [附源码]Python计算机毕业设计SSM化妆品网上商城数据分析系统(程序+LW)
项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclis ...
- 计算机毕设(附源码)JAVA-SSM化妆品网上商城数据分析系统
项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclis ...
最新文章
- FormData 的使用
- android 5. 蓝牙 mesh,蓝牙mesh组网
- 为什么国内流行hbase,国外反而多用cassandra?
- 深度学习笔记(43) Siamese网络
- 计算机主板芯片组型号有哪些,怎么才能知道自己的主板芯片的型号?
- Oracle11g补丁安装(单实例)
- Flume avro client和hdfs sink 完成自定义目录文件收集
- 5.Django路由path和re_path详解
- 很多人看都哭了,不信你不哭
- sqlserver 附加数据库方法
- BugKu CTF(杂项篇MISC)—想要种子吗
- 小程序 和 web 功能对比_小程序官方推出的Kbone,是如何解决Web 端和小程序同构痛点的?...
- unity pdg 设置隐藏不需要的节点以及实现自动勾选自动加载项
- oracle中rollback命令,9.2.4 执行ROLLBACK命令
- Spine之三——实用技巧大全
- 【数据分析】疫情对美国民众消费的影响研究报告
- 设计一个Windows窗体程序,设置程序,其运行结果如下图所示。垂直滚动条控制字体大小。
- mx player android5.1,MX Player
- 收到263定时发送邮件的发送提醒
- NFT首例诉讼?NBA Top Shot用户起诉Dapper Labs及其首席执行官