目录

1.明确需求和目的

  • 对一家全球超市四年(2011-2014)的销售数据进行 人、货、场分析,并给出提升销量的针对性建议。
  • :整体运营情况分析,包括销售额、销量、利润、客单价、市场布局等具体情况分析。
  • :商品结构、优势/爆款商品、劣势/待优化商品等情况分析。
  • :客户数量、新老客户、RFM模型、复购率、回购率等用户行为分析。

2.数据收集

  • 数据来源为kaggle平台,这是一份全球大型超市四年的零售数据集,数据详尽。
  • 数据集为superstore_dataset2011-2015.csv,共有51290条数据,共24个特征。

3.数据预处理

3.1 数据整合
3.1.1 加载相关库和数据集
  • 使用的库主要有:pandas、numpy、matplotlib、seaborn
  • 使用的数据集:superstore_dataset2011-2015.csv
# 加载数据分析需要使用的库
import
 numpy 
as
 np

import
 pandas 
as
 pd

import
 matplotlib.pyplot 
as
 plt

import
 seaborn 
as
 sns

import
 warnings


plt.rcParams[
'font.sans-serif'
] = [
'SimHei'
]

warnings.filterwarnings(
'ignore'
)



# 加载零售数据集,使用'ISO-8859-1'编码方式
df = pd.read_csv(
'superstore_dataset2011-2015.csv'
,encoding=
'ISO-8859-1'

df.head()

结果如下:
3.1.2 数据概览
首先看一下数据集大小(行列信息)。
df.shape

# ---------------
(
51290
24
)

再查看一下数据的分布概况。
# df.info()
df.describe()

结果如下:
3.2 数据清洗
3.2.1 列名重命名
观察数据集可以发现,列名存在着不符合Python标准的命名规范,因此对列名进行一下重命名,采用下划线命名法。
df.rename(columns = 
lambda
 x: x.replace(
' '
'_'
).replace(
'-'
'_'
), inplace=
True
)

再次查看一下重命名后的列名。
df.columns

-----------------

Index([
'Row_ID'
'Order_ID'
'Order_Date'
'Ship_Date'
'Ship_Mode'
,

'Customer_ID'
'Customer_Name'
'Segment'
'City'
'State'
'Country'
,

'Postal_Code'
'Market'
'Region'
'Product_ID'
'Category'
,

'Sub_Category'
'Product_Name'
'Sales'
'Quantity'
'Discount'
,

'Profit'
'Shipping_Cost'
'Order_Priority'
],

      dtype=
'object'
)

3.2.2  数据类型处理
查看一下每一列的数据类型。
df.dtypes

-----------------

Row_ID              int64

Order_ID           object

Order_Date         object

Ship_Date          object

Ship_Mode          object

Customer_ID        object

Customer_Name      object

Segment            object

City               object

State              object

Country            object

Postal_Code       float64

Market             object

Region             object

Product_ID         object

Category           object

Sub_Category       object

Product_Name       object

Sales             float64

Quantity            int64

Discount          float64

Profit            float64

Shipping_Cost     float64

Order_Priority     object

dtype: object

可以看到:大部分列是object类型,销量、销售额、利润等列是数值型,这些列都不需要进行数据类型处理。下单日期应为datetime类型,我们需要对其进行处理。
df[
"Order_Date"
] = pd.to_datetime(df[
"Order_Date"
]) 

df[
"Order_Date"
].sample(
5
)

----------------------------------

93192013-04-10
303902012-03-19
310252013-08-19
322102014-03-20
434302012-11-26
Name: Order_Date, dtype: datetime64[ns]

为了便于分析每年和每月的销售情况,新增加年份列月份列
df[
'year'
] = df[
"Order_Date"
].dt.year

df[
'month'
] = df[
'Order_Date'
].values.astype(
'datetime64[M]'
)

3.2.3 缺失值处理
我们再来查看一下各列的缺失值情况。
df.isnull().sum(axis=
0
)

----------------------------

Row_ID                
0
Order_ID              
0
Order_Date            
0
Ship_Date             
0
Ship_Mode             
0
Customer_ID           
0
Customer_Name         
0
Segment               
0
City                  
0
State                 
0
Country               
0
Postal_Code       
41296
Market                
0
Region                
0
Product_ID            
0
Category              
0
Sub_Category          
0
Product_Name          
0
Sales                 
0
Quantity              
0
Discount              
0
Profit                
0
Shipping_Cost         
0
Order_Priority        
0
year                  
0
month                 
0
dtype: int64

通过观察发现,有一列缺失值比较多,此列表示邮编信息,由于该列对我们的分析没有太多作用,可直接删除
df.drop([
"Postal_Code"
],axis=
1
, inplace=
True
)

3.2.4 异常值处理
查看数据是否存在异常值。
df.describe()

结果如下:
没发现明显的异常值,不需要进行处理。
3.2.5 重复值处理
看一下每一行数据是否存在重复值。
df.duplicated().sum()

---------------------

0
也没有重复值,不需要进行处理。

4.数据分析

4.1 整体销售情况分析
首先构造整体销售情况子数据集。
# 整体销售情况子数据集,包含下单日期、销售额、销量、利润、年份、月份信息
sales_data = df[[
'Order_Date'
,
'Sales'
,
'Quantity'
,
'Profit'
,
'year'
,
'month'
]]

sales_data.sample(
5
)  

------------------------------

  Order_Date Sales Quantity Profit year month

454362014-11-2738.040212.172820142014-11-01
126252013-11-1120.36817.383420132013-11-01
248002011-11-1540.320714.000020112011-11-01
355082014-01-2227.93649.428420142014-01-01
391832013-06-24179.880661.080020132013-06-01
按照年份、月份对销售子数据集进行分组求和。
sales_year = sales_data.groupby([
'year'
,
'month'
]).sum()

sales_year

结果如下:
对以上数据进行拆分,每年为一个表。
#  slice(None), 是Python中的切片操作,这里用来选择全部数据
year_2011 = sales_year.loc[(
2011
,slice(
None
)),:].reset_index()

year_2012 = sales_year.loc[(
2012
,slice(
None
)),:].reset_index()

year_2013 = sales_year.loc[(
2013
,slice(
None
)),:].reset_index()

year_2014 = sales_year.loc[(
2014
,slice(
None
)),:].reset_index()

year_2014    
# 看一下2014年的数据
结果如下:
4.1.1 销售额分析
构建销售表。
sales=pd.concat([year_2011[
'Sales'
],year_2012[
'Sales'
],

                 year_2013[
'Sales'
],year_2014[
'Sales'
]],axis=
1
)


# 对行名和列名进行重命名
sales.columns=[
'Sales-2011'
,
'Sales-2012'
,
'Sales-2013'
,
'Sales-2014'
]

sales.index=[
'Jau'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
]


# 颜色越深,销售额越高
sales.style.background_gradient()

结果如下:
从上图可以看出,基本上每一年都是下半年销售额比上半年要高,而且随着年份的增大,销售额也有明显的增加,说明销售业绩增长较快,发展还是比较好的。
肉眼可见的是每一年的销售额都比前一年要好,来实际计算一下具体的增长率和每年的销售总额。
# 计算年度销售额并图表展示
sales_sum=sales.sum()

sales_sum.plot(kind=
'bar'
,alpha=
0.5
)

plt.grid()


# 计算每年增长率
rise_12=sales_sum[
1
]/sales_sum[
0
]
-1
rise_13=sales_sum[
2
]/sales_sum[
1
]
-1
rise_14=sales_sum[
3
]/sales_sum[
2
]
-1
rise_rate=[
0
,rise_12,rise_13,rise_14]


# 显示增长率
sales_sum=pd.DataFrame({
'sales_sum'
:sales_sum})

sales_sum[
'rise_rate'
]=rise_rate

sales_sum

------------------------------------------

    sales_sum rise_rate

Sales
-20112.259451e+060.000000
Sales
-20122.677439e+060.184995
Sales
-20133.405746e+060.272017
Sales
-20144.299866e+060.262533
结果如下:
从上面可以看出,后两年的销售额增长率达到26%,2014年销售额将近是2011的两倍,发展势头良好,经营在逐步稳定。结合年度销售额及增长率,再结合公司整体战略规划,可以预测或制定下一年度总销售额业绩指标。
了解了超市整体销售额后,再对每年每月的销售额进行分析,了解不同月份的销售情况,找出是否有淡旺季之分,找出重点销售月份,以便制定经营策略与业绩月度及季度指标拆分。
看一下销售额的面积堆叠图。
# 面积堆叠图
sales.plot.area(stacked=
False
)

结果如下:
从上图可以大致看出,该超市的销售季节性明显,总体上半年是淡季,下半年是旺季。上半年中6月份销售额比较高,下半年中7月份的销售额偏低。
  • 对于旺季的月份,运营推广等策略要继续维持,还可以加大投入,提高整体销售额。
  • 对于淡季的月份,可以结合产品特点进行新产品拓展,举办一些促销活动等吸引客户。
4.1.2 销量分析
构建销量表。
quantity = pd.concat([year_2011[
'Quantity'
],year_2012[
'Quantity'
],

                 year_2013[
'Quantity'
],year_2014[
'Quantity'
]],axis=
1
)


# 对行名和列名进行重命名
quantity.columns=[
'Quantity-2011'
,
'Quantity-2012'
,
'Quantity-2013'
,
'Quantity-2014'
]

quantity.index=[
'Jau'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
]


# 颜色越深,销量越高
quantity.style.background_gradient()

结果如下:
看一下销量增长率和每年的销量总和。
# 计算年度销量并图表展示
quantity_sum=quantity.sum()

quantity_sum.plot(kind=
'bar'
,alpha=
0.5
)

plt.grid()


# 计算每年增长率
rise_12=quantity_sum[
1
]/quantity_sum[
0
]
-1
rise_13=quantity_sum[
2
]/quantity_sum[
1
]
-1
rise_14=quantity_sum[
3
]/quantity_sum[
2
]
-1
rise_rate=[
0
,rise_12,rise_13,rise_14]


# 显示增长率
quantity_sum=pd.DataFrame({
'quantity_sum'
:quantity_sum})

quantity_sum[
'rise_rate'
]=rise_rate

quantity_sum

------------------------------

   quantity_sum rise_rate

Quantity
-2011314430.000000
Quantity
-2012381110.212066
Quantity
-2013481360.263047
Quantity
-2014606220.259390
结果如下:
从上面可以看出,2011-2014年销量变化趋势与销售额是一样的,下半年销量整体高于上半年,同时销量同比上一年均在提高。
4.1.3 利润分析
构建利润表。
profit=pd.concat([year_2011[
'Profit'
],year_2012[
'Profit'
],

                 year_2013[
'Profit'
],year_2014[
'Profit'
]],axis=
1
)

profit.columns=[
'Profit-2011'
,
'Profit-2012'
,
'Profit-2013'
,
'Profit-2014'
]

profit.index=[
'Jau'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
]


profit.style.background_gradient()

结果如下:
计算每年总利润和利润率。
# 计算年度总利润并图表展示
profit_sum=profit.sum()

profit_sum.plot(kind=
'bar'
,alpha=
0.5
)

plt.grid()


profit_sum=pd.DataFrame({
'profit_sum'
:profit_sum})

profit_sum[
"year"
] =  [
2011
2012
2013
2014
]


sales_sum=pd.DataFrame({
'sales_sum'
:sales.sum()})

sales_sum[
"year"
] =  [
2011
2012
2013
2014
]


profit_sum = pd.merge(profit_sum, sales_sum)

profit_sum[
"profit_rate"
] = profit_sum[
"profit_sum"
] / profit_sum[
"sales_sum"
]

profit_sum

-----------------------------

  profit_sum year sales_sum profit_rate

0248940.8115420112.259451e+060.110178
1307415.2791020122.677439e+060.114817
2406935.2301820133.405746e+060.119485
3504165.9704620144.299866e+060.117252
结果如下:
从上面的结果可以看出,每年的利润和销售额一样,是在逐年增加的,说明企业经营还是比较妥善的,但是利润率总体平稳,稳定在11%-12%之间,总体利润率也还是不错的。
4.1.4 客单价分析
客单价:是指商场(超市)每一个顾客平均购买商品的金额,客单价也即是平均交易金额。从某种程度上反映了企业的消费群体的许多特点以及企业的销售类目的盈利状态是否健康。
总消费次数:同一天内,同一个人发生的所有消费算作一次消费。
客单价=总消费金额 / 总消费次数
# 2011-2014年客单价
for
 i 
in
 range(
2011
,
2015
):

    data=df[df[
'year'
]==i]

    price=data[[
'Order_Date'
,
'Customer_ID'
,
'Sales'
]]


# 计算总消费次数
    price_dr=price.drop_duplicates(

        subset=[
'Order_Date'
'Customer_ID'
])


# 总消费次数:有多少行
    total_num=price_dr.shape[
0
]

    print(
'{}年总消费次数='
.format(i),total_num)


    unit_price = price[
'Sales'
].sum()/total_num

    print(
'{}年客单价='
.format(i), unit_price,
'\n'
)

---------------------------------------------------

2011
年总消费次数= 
4453
2011
年客单价= 
507.3997070604087

2012
年总消费次数= 
5392
2012
年客单价= 
496.55762136498515

2013
年总消费次数= 
6753
2013
年客单价= 
504.3308824788983

2014
年总消费次数= 
8696
2014
年客单价= 
494.4647965225392
从上面结果来看,每年的消费次数呈不断上升趋势,但是客单价总体浮动范围不是很大 ,稳定在500左右。
4.1.5 市场布局分析
因为这是一家全球超市,在不同地区都会有市场,所以看一下不同地区之间的销售情况。
Market_Year_Sales = df.groupby([
'Market'
'year'
]).agg({
'Sales'
:
'sum'
}).reset_index().rename(columns={
'Sales'
:
'Sales_amounts'
})

Market_Year_Sales.head()

--------------------------------

 Market year Sales_amounts

0
 APAC 
20116.392453e+05
1
 APAC 
20127.627193e+05
2
 APAC 
20139.745809e+05
3
 APAC 
20141.209199e+06
4
 Africa 
20111.271873e+05
用图表显示各个地区每年的销售情况。
sns.barplot(x=
'Market'
, y=
'Sales_amounts'
, hue=
'year'
, data = Market_Year_Sales)

plt.title(
'2011-2014 market sales'
)

结果如下:
再看一下四年来各个地区销售额占总销售额的百分比。
Market_Sales = df.groupby([
'Market'
]).agg({
'Sales'
:
'sum'
})

Market_Sales[
"percent"
] = Market_Sales[
"Sales"
] / df[
"Sales"
].sum()

Market_Sales.style.background_gradient()

结果如下:
从以上图表可以看出,每个地区每年销售额总体处于上升趋势,其中APAC(亚太地区)、EU(欧盟)、US(美国)、LATAM(拉丁美洲)的销售额超过了总销售额的85%,总体也与地区的经济发展相匹配。其中加拿大Canada的销售额微乎其微,可以结合公司整体战略布局进行取舍。
4.2 商品情况分析
销量前10名的商品。
productId_count = df.groupby(
'Product_ID'
).count()[
'Customer_ID'
].sort_values(ascending=
False
)

print(productId_count.head(
10
))

--------------------------------------

Product_ID

OFF-AR
-1000365135
OFF-AR
-1000382931
OFF-BI
-1000279930
OFF-BI
-1000370830
FUR-CH
-1000335428
OFF-BI
-1000257027
OFF-BI
-1000414025
OFF-BI
-1000419524
OFF-BI
-1000180824
OFF-BI
-1000463224
Name: Customer_ID, dtype: int64

销售额前10名的商品。
productId_amount = df.groupby(
'Product_ID'
).sum()[
'Sales'
].sort_values(ascending=
False
)

print(productId_amount.head(
10
))

-----------------------------------

Product_ID

TEC-CO
-1000472261599.8240
TEC-PH
-1000466430041.5482
OFF-BI
-1000352727453.3840
TEC-MA
-1000241222638.4800
TEC-PH
-1000482322262.1000
FUR-CH
-1000202421870.5760
FUR-CH
-1000002721329.7300
OFF-AP
-1000451221147.0840
FUR-TA
-1000188920730.7557
OFF-BI
-1000135919823.4790
Name: Sales, dtype: float64

从上面可以看出,销量最高的大部分是办公用品,而销售额最高的大部分是电子产品、家具这些单价较高的商品。
利润前10的商品。
productId_Profit= df.groupby(
'Product_ID'
).sum()[
'Profit'
].sort_values(ascending=
False
)

print(productId_Profit.head(
10
))

------------------------------------

Product_ID

TEC-CO
-1000472225199.9280
OFF-AP
-1000451210345.5840
TEC-PH
-100048238121.4800
OFF-BI
-100035277753.0390
TEC-CO
-100014496983.8836
FUR-CH
-100022506123.2553
TEC-PH
-100046645455.9482
OFF-AP
-100023305452.4640
TEC-PH
-100003035356.8060
FUR-CH
-100022035003.1000
Name: Profit, dtype: float64

利润前10的商品有一半是电子产品,可以重点考虑提升这部分产品的销量,来增加整体的利润。
具体商品种类的销售情况。
# 根据商品种类和子种类,重新重合成一个新的种类
df[
'Category_Sub_Category'
] = df[[
'Category'
,
'Sub_Category'
]].apply(
lambda
 x:str(x[
0
])+
'_'
+str(x[
1
]),axis=
1
)

# 按照新的种类进行分组,统计销售额和利润
df_Category_Sub_Category=df.groupby(
"Category_Sub_Category"
).agg({
"Profit"
:
"sum"
,
"Sales"
:
"sum"
}).reset_index()

# 按照销售额倒序排序
df_Category_Sub_Category.sort_values(by=[
"Sales"
],ascending=
False
, inplace=
True
)

# 每个种类商品的销售额累计占比
df_Category_Sub_Category[
'cum_percent'
] = df_Category_Sub_Category[
'Sales'
].cumsum()/df_Category_Sub_Category[
'Sales'
].sum()

df_Category_Sub_Category

结果如下:
从图表中可以很清晰的看到不同种类商品的销售额贡献对比,有将近一半的商品的总销售占比达到84%,应该是自家优势主营产品,后续经营中应继续保持,可以结合整体战略发展适当加大投入,逐渐形成自己的品牌。
同时,也可以发现,末尾占比16%的产品中大部分是办公用品中的小物件。可以考虑与其他主营产品结合,连带销售来提升销量,或者考虑对这些商品进行优化。
但是值得关注的是,Tables(桌子)的利润是负,表明这个产品目前处于亏损状态,应该是促销让利太多。通过检查原数据,发现Tabels大部分都在打折,打折的销量高达76%。如果是在清库存,这个效果还是不错的,但如果不是,说明这个产品在市场推广上遇到了瓶颈,或者是遇到强竞争对手,需要结合实际业务进行分析,适当改善经营策略。
4.3 用户情况分析
4.3.1 不同类型的客户占比
df[
"Segment"
].value_counts().plot(kind=
'pie'
, autopct=
'%.2f%%'
, shadow=
True
, figsize=(
14
6
))

结果如下:
从上图可以看出,这四年来,普通消费者的客户占比最多,达到51.7%。
再看一下每一年不同类型的客户数量情况。
Segment_Year = df.groupby([
"Segment"
'year'
]).agg({
'Customer_ID'
:
'count'
}).reset_index()

sns.barplot(x=
'Segment'
, y=
'Customer_ID'
, hue=
'year'
, data = Segment_Year)

plt.title(
'2011-2014 Segment Customer'
)

结果如下:
从上面可以看出,每类客户每年均在保持增长趋势,客户结构还是非常不错的。
看一下不同类型的客户每年贡献的销售额。
Segment_sales = df.groupby([
"Segment"
'year'
]).agg({
'Sales'
:
'sum'
}).reset_index()

sns.barplot(x=
'Segment'
, y=
'Sales'
, hue=
'year'
, data = Segment_sales)

plt.title(
'2011-2014 Segment Sales'
)

结果如下:
各个类型的客户每年贡献的销售额都在稳步提升,普通消费者贡献的销售额最多,这和客户占比也有一定关系。
4.3.2 客户下单行为分析
首先截取Customer_ID, Order_Date, Quantity, Sales, month为新的子集,并对Order_Date进行排序,方便后续分析 :
grouped_Customer = df[[
'Customer_ID'
,
'Order_Date'

'Quantity'
'Sales'
'month'
]].sort_values([
'Order_Date'
]).groupby(
'Customer_ID'
)

grouped_Customer.head()

结果如下:
看一下用户的第一次购买日期分布。
grouped_Customer.min().Order_Date.value_counts().plot()

结果如下:
再来看一下用户的最后一次购买日期分布。
grouped_Customer.max().Order_Date.value_counts().plot()

结果如下:
从上面可以看出, 在13年初以后新用户增长的趋势缓慢,商家可以通过广告等推广策略吸收更多的新用户;而通过观察最近一次购买日期,可以发现用户基本没有流失,也验证了每年销售额的增长趋势。
总体来说新客户数量是在逐年递减的,说明该企业老客户的维系不错,但新客获取率较低。如果能够在新客户获取上能够突破,会给企业带来很大的增长空间。
再来看看只购买过一次的客户数量 。
# 统计每个客户第一次和最后一次购买记录
Customer_life = grouped_Customer.Order_Date.agg([
'min'
,
'max'
])

# 查看只有一次购买记录的顾客数量,第一次和最后一次是同一条记录,则说明购买只有一次
(Customer_life[
'min'
] == Customer_life[
'max'
]).value_counts()

-----------------------------------------------------

False1580
True10
dtype: int64

从结果来看,只购买一次的用户只有10个,大部分用户都会购买多次,说明回头率很高,也验证了上面关于该企业老客户的维系不错的结论。
4.3.3 RFM模型分析
RFM的含义:
  • R(Recency):客户最近一次交易时间的间隔。R值越大,表示客户交易发生的日期越久,反之则表示客户交易发生的日期越近。
  • F(Frequency):客户在最近一段时间内交易的次数。F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。
  • M(Monetary):客户在最近一段时间内交易的金额。M值越大,表示客户价值越高,反之则表示客户价值越低。
RFM分析就是根据客户活跃程度和交易金额的贡献,进行客户价值细分的一种方法。
首先构建RFM表。
rfm = df.pivot_table(index=
'Customer_ID'
,

                    values = [
"Quantity"
,
"Sales"
,
"Order_Date"
],

              aggfunc={
"Quantity"
:
"sum"
,
"Sales"
:
"sum"
,
"Order_Date"
:
"max"
})


# 所有用户最大的交易日期为标准,求每笔交易的时间间隔即为R
rfm[
'R'
] = (rfm.Order_Date.max() - rfm.Order_Date)/np.timedelta64(
1
,
'D'
)

# 每个客户的总销量即为F,总销售额即为M
rfm.rename(columns={
'Quantity'
:
'F'
,
'Sales'
:
'M'
},inplace = 
True
)

rfm.head()

结果如下:
接着对客户价值进行标注,将客户分为8个等级。
# 基于平均值做比较,超过均值为1,否则为0
rfm[[
'R'
,
'F'
,
'M'
]].apply(
lambda
 x:x-x.mean())


defrfm_func(x):
    level =x.apply(
lambda
 x:
'1'if
 x>
0else'0'
)

    level =level.R +level.F +level.M

    d = {

"111"
:
"重要价值客户"
,

"011"
:
"重要保持客户"
,

"101"
:
"重要挽留客户"
,

"001"
:
"重要发展客户"
,

"110"
:
"一般价值客户"
,

"010"
:
"一般保持客户"
,

"100"
:
"一般挽留客户"
,

"000"
:
"一般发展客户"
    }

    result = d[level]

return
 result


rfm[
'label'
]= rfm[[
'R'
,
'F'
,
'M'
]].apply(
lambda
 x:x-x.mean()).apply(rfm_func,axis =
1
)

rfm.head()

结果如下:
对重要价值客户和非重要价值客户进行可视化展示。
rfm.loc[rfm.label==
'重要价值客户'
,
'color'
]=
'g'
rfm.loc[~(rfm.label==
'重要价值客户'
),
'color'
]=
'r'
rfm.plot.scatter(
'F'
,
'R'
,c= rfm.color)

结果如下:
通过RFM识别不同的客户群体,能够衡量客户价值和客户利润创收能力,可以指定个性化的沟通和营销服务,为更多的营销决策提供有力支持,为企业创造更大的利益。
4.3.4  新用户、活跃用户、不活跃用户和回归用户分析
设置Customer_ID为索引,month为列名,统计每个月的购买次数。
pivoted_counts = df.pivot_table(index= 
'Customer_ID'
,

                               columns= 
'month'
,

                               values= 
'Order_Date'
,

                               aggfunc= 
'count'
).fillna(
0
)

# 大于一次的全部设为1
df_purchase = pivoted_counts.applymap(
lambda
 x:
1if
 x>
0else0
)

df_purchase.head()

结果如下:
定义状态函数并进行状态标记。
defactive_status(data):
    status = []

for
 i 
in
 range(
48
):

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
:

# 新用户
                status.append(
"new"
)

else
:

if
 status[i
-1
] == 
"unactive"
:

# 回归用户
                    status.append(
"return"
)

elif
 status[i
-1
] == 
"unreg"
:

                    status.append(
"new"
)

else
:

                    status.append(
"active"
)

return
 pd.Series(status)  


purchase_stats = df_purchase.apply(active_status,axis =
1
)

purchase_stats.head()

结果如下:
用NaN替代 "unreg",并统计每月各状态客户数量。
purchase_stats_ct = purchase_stats.replace(
'unreg'
,np.NaN).apply(
lambda
 x:pd.value_counts(x))

# 用0填充NaN
purchase_stats_ct.fillna(
0
).T.plot.area()

结果如下:
从以上结果可以发现活跃客户、新客户和回归客户,每年呈一定的规律起伏,这可能和年终年末大促有关,需要更多数据进行佐证;同时可以发现新客数量每年均在减少,说明该商家新客获取率较低,如果能在新客户获取上取得突破,会给商家带来很大的增长空间。
4.3.5 复购率和回购率分析
  • 复购率计算指标:用户在该月购买过一次以上算复购。
purchase_r = pivoted_counts.applymap(
lambda
 x :
1if
 x>
1else
 np.NaN 
if
 x==
0else0
)

(purchase_r.sum()/purchase_r.count()).plot(figsize=(
10
,
4
))

结果如下:
  • 回购率计算指标:在该月购买过,且在下月也购买时计入回购。
defpurchase_back(data):
    status=[]

for
 i 
in
 range(
47
):

if
 data[i] ==
1
:

if
 data[i+
1
] == 
1
:

                status.append(
1
)

if
 data[i+
1
] == 
0
:

                status.append(
0
)

else
:

            status.append(np.NaN)

    status.append(np.NaN)

return
 status


purchase_b = df_purchase.apply(purchase_back,axis =
1
,result_type=
'expand'
)

(purchase_b.sum()/purchase_b.count()).plot(figsize=(
10
,
4
))

结果如下:
从上可以发现复购率基本大于0.525,且呈总体上升趋势,说明客户忠诚度高,回购率在年中年末呈峰形态,可能与商家折扣活动或节日有关。

5.总结

本文分别通过 场、货、人 三个不同的角度去分析一家全球超市的销售、商品、用户情况,并根据分析结果给出一些有利于拓展用户、提升销量的办法。当然,这份数据集包含信息很多,还可以进行其它一些方面的分析,来给出更好的建议。
文本经过作者授权发布。如果觉得文章对你有帮助,欢迎关注作者的CSDN博客号,精彩抢先看。
关注微信公众号『数据分析与统计学之美』,后台回复“超市零售数据”自动获取本文的数据。
如果觉得写得好,好文点再看和朋友一起分享!
继续阅读
阅读原文