Python 某电子产品销售数据分析报告及RFM模型(一)

关注微信公共号:小程在线

关注CSDN博客:程志伟的博客

Python 3.7.6 (default, Jan  8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 7.12.0 -- An enhanced Interactive Python.

'''
1结论总结先行:
总结:
1-8月份运营效果较好,其中4、5、7、8月是非常好的,9月份开始运营的效果就越来越差,应该再进一步分析为什么会出现这个现象,还有复盘618与双十一的活动。
总指标:
总GMV约1.15亿元,7月8月的GMV上升非常大,8月达到峰值,然后就开始下降。
总的客单价:按客户数量为1240元/人;按订单数量为296元/单。
其他指标:
4月比3月新增用户多了差不多2倍,5月又比4月多了2.3倍,7月份比6月份增多了1.5倍,8月份与7月份持平,证明4、5、7、8月的拉新效果比较好。
复购率1-3月在上升,然后4月份下降到比1月份还低,进一步分析,4月份进行了拉新活动,较多新客当月只购买了一次(有可能是因为拉新活动启动比较晚,新客的复购周期还没到;也有可能这批新客在4月的购买满意度较低,应该着重分析这批客户是否有投诉),所以造成复购率下降。
回购人数在1-8月均上升,9月份开始快速下降,虽然回购人数前几个月在上升,但是整体回购率却是在下降,可见老客的回头率在不断下降,也就证明我们的产品留不住大部分的客户。
销售情况分析:
广东、上海、北京的销售额、销量以及客户数量都是最高的。
销售额与销量1-8月呈上升趋势,8月达到峰值,5、7、8月上升较大,这三个月的新客户都有增长,幅度也不少,证明拉新活动效果不错;9月销售额与销量和新客都开始下降,其中新客的下单量减少了四分之三,证明9月份的拉新活动效果非常差。同时发现618和双十一当天的销售情况非常差。
用户角度:
用户喜欢周六日进行购物,可以在周末多推送商品给用户,适当推销一两款要清仓的商品给用户;喜欢在早上6点至中午12点之间进行购物,也可以在该时间段推送商品给用户。
目前客户最多的是广东(21382),然后是上海(16031),北京(15928),其他8个城市比较平均(5400上下),根据2020年人口普查,广东拥有全国常住人口最多(达1.2亿人),客户仅占0.017%,最高客户占比是北京(0.0728%),约为广东的4倍,所以在广东加大投入拉新活动的性价比是最高的。
目前的客户男女各占一半,总体上在16-50岁之间平均分布。
前27%的用户贡献了80%的销售收入,且客户平均消费金额大于75%的分位数(存在高消费用户),这批用户要做好跟进,一定要留住这批贡献大的客户。
消费两次及以上的客户有50%消费周期为7天内,75%为26天内,消费周期较短。
产品角度:
得出了销量前10和销售额前10的产品,要时刻关注他们的库存量,避免发生缺货现象。
对于产品销量少于10的产品,可以考虑促销活动对其进行清仓处理。
最受欢迎的产品类别是smartphone-即手机,是第二名手提电脑的4倍。
手机销量前五分别为三星、苹果、小米、华为、OPPO,其中三星占了一半以上的份额,苹果约占据了四分之一;分析发现各年龄段和男性女性购买三星、苹果手机都是比较平均的,也发现广东、上海、北京占了50%以上的销量。
RFM模型分析:
重要的客户共有44129人
其中重要价值客户有20012人,约占重要客户的50%,对于重要价值客户,要给与他们VIP式的服务,时刻留意他们的购买反馈
重要发展客户有4415人,这类客户消费频率不够高,要想办法提高他们的消费频率,例如发放满减卷等
重要保持客户有11368人,这类客户最后一次购买时间距离现在已经很远了,应该发送信息,或者电话联系他们,也可以发放满减卷给他们,提高他们的复购率
重要挽留客户有8334人,要想办法挽回这批将近流失的客户,也可以通过短信召回,发放优惠券.
一般的客户共有48626人
对于一般价值、一般发展、一般保持的客户,在处理好重要客户的情况下,可以酌情去发展维系这批客户。
其中一般挽留用户有26843人,这类客户是要流失的,所以在没有多余资源的情况下,就放弃这批客户吧。
'''

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime

plt.rcParams['font.sans-serif'] = ['SimHei']  #设置中文字体为黑体
plt.rcParams['axes.unicode_minus'] = False #正常显示负号

pd.set_option('display.float_format',lambda x : '%.2f' % x)#pandas禁用科学计数法

#忽略警告
import warnings
warnings.filterwarnings('ignore')

'''
2字段介绍:
Unnamed: 行号
event_time:下单时间
order_id:订单编号
product_id:产品标号
category_id :类别编号
category_code :类别
brand :品牌
price :价格
user_id :用户编号
age :年龄
sex :性别
local:省份
'''

data = pd.read_csv(r'F:\Python\电子产品销售分析.csv',index_col=0,dtype={'category_id':'int64','user_id':'int64'})
data.head()
Out[2]: 
                event_time             order_id  ...  sex  local
0  2020-04-24 11:50:39 UTC  2294359932054536986  ...    女     海南
1  2020-04-24 11:50:39 UTC  2294359932054536986  ...    女     海南
2  2020-04-24 14:37:43 UTC  2294444024058086220  ...    女     北京
3  2020-04-24 14:37:43 UTC  2294444024058086220  ...    女     北京
4  2020-04-24 19:16:21 UTC  2294584263154074236  ...    女     广东

[5 rows x 11 columns]

####3创建新列-日期、月份、小时、周几
#创建日期列

data['date'] = data.event_time.apply(lambda x: x.split(' ')[0])

data['date'] = pd.to_datetime(data['date'])

#创建月份列

data['month'] = data.date.dt.month

#创建"小时"列

data['hour'] = data.event_time.apply(lambda x: x.split(' ')[1].split(':')[0])

#创建周几列---周日为0,周一为1

data['weekday'] = data.date.apply(lambda x:x.strftime("%w"))

#删除event_time列

del data['event_time']

data.head()
Out[9]: 
              order_id           product_id  ...  hour weekday
0  2294359932054536986  1515966223509089906  ...    11       5
1  2294359932054536986  1515966223509089906  ...    11       5
2  2294444024058086220  2273948319057183658  ...    14       5
3  2294444024058086220  2273948319057183658  ...    14       5
4  2294584263154074236  2273948316817424439  ...    19       5

[5 rows x 14 columns]

####4查看数据缺失、重复情况

data.shape
Out[10]: (564169, 14)

data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 564169 entries, 0 to 2633520
Data columns (total 14 columns):
 #   Column         Non-Null Count   Dtype         
---  ------         --------------   -----         
 0   order_id       564169 non-null  int64         
 1   product_id     564169 non-null  int64         
 2   category_id    564169 non-null  int64         
 3   category_code  434799 non-null  object        
 4   brand          536945 non-null  object        
 5   price          564169 non-null  float64       
 6   user_id        564169 non-null  int64         
 7   age            564169 non-null  float64       
 8   sex            564169 non-null  object        
 9   local          564169 non-null  object        
 10  date           564169 non-null  datetime64[ns]
 11  month          564169 non-null  int64         
 12  hour           564169 non-null  object        
 13  weekday        564169 non-null  object        
dtypes: datetime64[ns](1), float64(2), int64(5), object(6)
memory usage: 64.6+ MB

'''
缺失数据有category_code-产品类别和brand-品牌这两列,对于category_code用"R"来代替缺失值而不是选择删除缺失值的数据
brand这一列数据缺失比较少,直接删除缺失值
'''

data['category_code'] = data['category_code'].fillna("R")

#删除brand这一列有缺失值的数据

data = data[data.brand.notnull()]

data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 536945 entries, 0 to 2633520
Data columns (total 14 columns):
 #   Column         Non-Null Count   Dtype         
---  ------         --------------   -----         
 0   order_id       536945 non-null  int64         
 1   product_id     536945 non-null  int64         
 2   category_id    536945 non-null  int64         
 3   category_code  536945 non-null  object        
 4   brand          536945 non-null  object        
 5   price          536945 non-null  float64       
 6   user_id        536945 non-null  int64         
 7   age            536945 non-null  float64       
 8   sex            536945 non-null  object        
 9   local          536945 non-null  object        
 10  date           536945 non-null  datetime64[ns]
 11  month          536945 non-null  int64         
 12  hour           536945 non-null  object        
 13  weekday        536945 non-null  object        
dtypes: datetime64[ns](1), float64(2), int64(5), object(6)
memory usage: 61.4+ MB

####4.1存在重复值,但是换个角度去想,这些重复值就是同笔订单下了多个数量的订单,所以不删除重复值,进而增加一列购买数量的列和总价的列
 

data.duplicated().sum()
Out[15]: 634

#添加新的列:购买数量

data = data.value_counts().reset_index().rename(columns={0:'buy_cnt'})
Traceback (most recent call last):

  File "<ipython-input-16-c9e31d7feae0>", line 1, in <module>
    data = data.value_counts().reset_index().rename(columns={0:'buy_cnt'})

  File "E:\anaconda3\lib\site-packages\pandas\core\generic.py", line 5274, in __getattr__
    return object.__getattribute__(self, name)

AttributeError: 'DataFrame' object has no attribute 'value_counts'

解决方法:
df = data.groupby(['order_id','product_id']).agg(buy_cnt=('user_id','count'))
data = pd.merge(data,df,on=['order_id','product_id'],how='inner')
data = data.drop_duplicates().reset_index(drop=True)

#添加新的列:购买总金额

data['amount'] = data['price'] * data['buy_cnt']

####5查看数据是否有异常
#5.1把几个id的格式转化为object格式

data.order_id = data.order_id.astype('object')
data.product_id = data.product_id.astype('object')
data.category_id = data.category_id.astype('object')
data.user_id = data.user_id.astype('object')

#5.2把hour和weekday转化为int

data['hour'] = data.loc[:,'hour'].astype('int')
data['weekday'] = data.loc[:,'weekday'].astype('int')

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 536311 entries, 0 to 536310
Data columns (total 16 columns):
 #   Column         Non-Null Count   Dtype         
---  ------         --------------   -----         
 0   order_id       536311 non-null  object        
 1   product_id     536311 non-null  object        
 2   category_id    536311 non-null  object        
 3   category_code  536311 non-null  object        
 4   brand          536311 non-null  object        
 5   price          536311 non-null  float64       
 6   user_id        536311 non-null  object        
 7   age            536311 non-null  float64       
 8   sex            536311 non-null  object        
 9   local          536311 non-null  object        
 10  date           536311 non-null  datetime64[ns]
 11  month          536311 non-null  int64         
 12  hour           536311 non-null  int32         
 13  weekday        536311 non-null  int32         
 14  buy_cnt        536311 non-null  int64         
 15  amount         536311 non-null  float64       
dtypes: datetime64[ns](1), float64(3), int32(2), int64(2), object(8)
memory usage: 61.4+ MB

#5.3查看价格和年龄是否存在异常值
#以上7个字段均没有异常值
#price和amount最小值为0,这类商品应该就是免费类的商品,所以也不属于异常值。
#应该进一步分析,购买了0元商品的用户,后续是否还有购买了其他的商品

data.describe(percentiles=[0.01,0.25,0.75,0.99]).T
Out[22]: 
            count   mean    std   min    1%   25%   50%    75%     99%      max
price   536311.00 214.54 305.98  0.00  1.13 24.51 99.51 289.33 1387.01 11574.05
age     536311.00  33.18  10.12 16.00 16.00 24.00 33.00  42.00   50.00    50.00
month   536311.00   7.72   2.56  1.00  1.00  6.00  8.00  10.00   11.00    11.00
hour    536311.00   9.52   4.21  0.00  1.00  6.00  9.00  12.00   22.00    23.00
weekday 536311.00   3.03   2.04  0.00  0.00  1.00  3.00   5.00    6.00     6.00
buy_cnt 536311.00   1.00   0.04  1.00  1.00  1.00  1.00   1.00    1.00     4.00
amount  536311.00 214.73 306.48  0.00  1.13 24.98 99.51 289.33 1387.01 11574.05

#5.4检查其他字段是否有异常值

data.describe(include='all').T
Out[23]: 
                  count    unique                    top  ...   50%    75%      max
order_id      536311.00 389511.00 2388440981134689792.00  ...   NaN    NaN      NaN
product_id    536311.00  19078.00 1515966223517847040.00  ...   NaN    NaN      NaN
category_id   536311.00    786.00 2268105428166508800.00  ...   NaN    NaN      NaN
category_code    536311       124                      R  ...   NaN    NaN      NaN
brand            536311       868                samsung  ...   NaN    NaN      NaN
price         536311.00       NaN                    NaN  ... 99.51 289.33 11574.05
user_id       536311.00  92769.00 1515915625512422912.00  ...   NaN    NaN      NaN
age           536311.00       NaN                    NaN  ... 33.00  42.00    50.00
sex              536311         2                      男  ...   NaN    NaN      NaN
local            536311        11                     广东  ...   NaN    NaN      NaN
date             536311       323    2020-10-22 00:00:00  ...   NaN    NaN      NaN
month         536311.00       NaN                    NaN  ...  8.00  10.00    11.00
hour          536311.00       NaN                    NaN  ...  9.00  12.00    23.00
weekday       536311.00       NaN                    NaN  ...  3.00   5.00     6.00
buy_cnt       536311.00       NaN                    NaN  ...  1.00   1.00     4.00
amount        536311.00       NaN                    NaN  ... 99.51 289.33 11574.05

[16 rows x 13 columns]

#5.4.1发现date日期有异常值,显示为1970-01-01,把这些异常值删除

data = data[data.date>'1970-01-01']

data.date.min()
Out[25]: Timestamp('2020-01-05 00:00:00')

至此数据已经清洗完成

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值