python数据分析实战---秦璐

讲解: 一份数据分析报告 #既包含代码又包含数据分析结果的PDF形式

  • Markdown写法 :说明
  • code import pandas as pd
    快捷切换 esc+m 变为Markdown/esc+m 变为code
  • 图形化呈现 :结果

练习1 这是一份用户消费行为的分析报告(数据来源于网络,用户在一家CD网站上的消费)

import pandas as pd
import numpy as np
#加载数据可视化包
import matplotlib.pyplot as plt
#可视化显示页面#%内置的符号,为jupyter专用,做好图之后可以直接在html页面显示
%matplotlib inline
#更改设计
plt.style.use('ggplot')#r语言风格
columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table('CDNOW_master.txt',names = columns,sep = '\s+',parse_dates= True)
  • user_id 用户名
  • order_dt 购买日期
  • order_products 购买产品数
  • order_amount 购买金额
df.head()#显示字段
user_idorder_dtorder_productsorder_amount
0119970101111.77
1219970112112.00
2219970112577.00
3319970102220.76
4319970330220.76
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 69659 entries, 0 to 69658
Data columns (total 4 columns):
user_id           69659 non-null int64
order_dt          69659 non-null int64
order_products    69659 non-null int64
order_amount      69659 non-null float64
dtypes: float64(1), int64(3)
memory usage: 2.1 MB

需要对order_dt进行清理

df.describe()
user_idorder_dtorder_productsorder_amount
count69659.0000006.965900e+0469659.00000069659.000000
mean11470.8545921.997228e+072.41004035.893648
std6819.9048483.837735e+032.33392436.281942
min1.0000001.997010e+071.0000000.000000
25%5506.0000001.997022e+071.00000014.490000
50%11410.0000001.997042e+072.00000025.980000
75%17273.0000001.997111e+073.00000043.700000
max23570.0000001.998063e+0799.0000001286.010000
  • 大部分订单只消费了少量商品(平均2.4),有一定极值干扰
  • 用户的消费金额比较稳定,平均消费35元,中位数在35,有一定极值干扰
df['order_dt'] = pd.to_datetime(df.order_dt,format = "%Y%m%d") #解析函数,转换某个字段的格式
df['month'] = df.order_dt.values.astype('datetime64[M]')
df
user_idorder_dtorder_productsorder_amountmonth
011997-01-01111.771997-01-01
121997-01-12112.001997-01-01
221997-01-12577.001997-01-01
331997-01-02220.761997-01-01
431997-03-30220.761997-03-01
531997-04-02219.541997-04-01
631997-11-15557.451997-11-01
731997-11-25420.961997-11-01
831998-05-28116.991998-05-01
941997-01-01229.331997-01-01
1041997-01-18229.731997-01-01
1141997-08-02114.961997-08-01
1241997-12-12226.481997-12-01
1351997-01-01229.331997-01-01
1451997-01-14113.971997-01-01
1551997-02-04338.901997-02-01
1651997-04-11345.551997-04-01
1751997-05-31338.711997-05-01
1851997-06-16226.141997-06-01
1951997-07-22228.141997-07-01
2051997-09-15340.471997-09-01
2151997-12-08446.461997-12-01
2251997-12-12340.471997-12-01
2351998-01-03337.471998-01-01
2461997-01-01120.991997-01-01
2571997-01-01228.741997-01-01
2671997-10-11797.431997-10-01
2771998-03-229138.501998-03-01
2881997-01-0119.771997-01-01
2981997-02-13113.971997-02-01
..................
69629235561997-09-27331.471997-09-01
69630235561998-01-03228.981998-01-01
69631235561998-06-07228.981998-06-01
69632235571997-03-25114.371997-03-01
69633235581997-03-25228.131997-03-01
69634235581997-05-18345.511997-05-01
69635235581997-06-24223.741997-06-01
69636235581998-02-25448.221998-02-01
69637235591997-03-25223.541997-03-01
69638235591997-05-18335.311997-05-01
69639235591997-06-27352.801997-06-01
69640235601997-03-25118.361997-03-01
69641235611997-03-25230.921997-03-01
69642235611998-01-28115.491998-01-01
69643235611998-05-29337.051998-05-01
69644235621997-03-25229.331997-03-01
69645235631997-03-25110.771997-03-01
69646235631997-10-04247.981997-10-01
69647235641997-03-25111.771997-03-01
69648235641997-05-21111.771997-05-01
69649235641997-11-30346.471997-11-01
69650235651997-03-25111.771997-03-01
69651235661997-03-25236.001997-03-01
69652235671997-03-25120.971997-03-01
69653235681997-03-25122.971997-03-01
69654235681997-04-05483.741997-04-01
69655235681997-04-22114.991997-04-01
69656235691997-03-25225.741997-03-01
69657235701997-03-25351.121997-03-01
69658235701997-03-26242.961997-03-01

69659 rows × 5 columns

1.进行用户消费趋势的分析(按月)

  • 每月的消费总金额
  • 每月的消费次数
  • 每月的产品购买量
  • 每月的消费人数
grouped_month = df.groupby('month')#数据的聚合
order_month_amount = grouped_month.order_amount.sum()#将order_amount按照grouped_month进行切片,求和
order_month_amount.head()#读取前5行
month
1997-01-01    299060.17
1997-02-01    379590.03
1997-03-01    393155.27
1997-04-01    142824.49
1997-05-01    107933.30
Name: order_amount, dtype: float64
#加载数据可视化包
import matplotlib.pyplot as plt
#可视化显示页面
%matplotlib inline 
#更改设计
plt.style.use('ggplot')#r语言风格
order_month_amount.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x228154dfba8>

[外链图片转存失败(img-QacSZRio-1567614745664)(output_14_1.png)]

由上图可知,消费金额在前三个月达到高峰,后续消费较为稳定,有轻微下降趋势
grouped_month.user_id.count().plot()#求出每月里的订单数
<matplotlib.axes._subplots.AxesSubplot at 0x228150d0898>

[外链图片转存失败(img-jCtrxOWZ-1567614745665)(output_16_1.png)]

前三个月消费订单数在10000笔左右,后续月份的平均消费人数则在2500人

grouped_month.order_products.sum().plot()#产品数需要使用sum,一单不只一个产品
<matplotlib.axes._subplots.AxesSubplot at 0x2281502c588>

在这里插入图片描述

df.groupby('month').user_id.apply(lambda x :len(x.drop_duplicates())).plot() #apply去重的操作,数组uesr_id作为输入,去重,len求个数
<matplotlib.axes._subplots.AxesSubplot at 0x228139590b8>

[外链图片转存失败(img-dQrBlh6t-1567614745665)(output_19_1.png)]

df.groupby(['month','user_id']).count().reset_index()  #第二种,通过groupby去重,重置索引
df.groupby('month').user_id.count().plot()
<matplotlib.axes._subplots.AxesSubplot at 0x2281579fe80>

[外链图片转存失败(img-JUEtZ9Rt-1567614745666)(output_20_1.png)]

每月的消费人数低于每月的消费次数,但差异不大;
前三个月每月的消费人数在8000-10000之间,后续月份,平均消费人数在2000人不到

#数据透视
df.pivot_table(index = 'month',
              values = ['order_products','order_amount','user_id'],
              aggfunc = {'order_products':'sum',
                         'order_amount':'sum',
                         'user_id':'count'}).head()#透视去重比较麻烦,不建议
order_amountorder_productsuser_id
month
1997-01-01299060.17194168928
1997-02-01379590.032492111272
1997-03-01393155.272615911598
1997-04-01142824.4997293781
1997-05-01107933.3072752895

问题:

  • 每月用户的平均消费金额趋势
  • 每月用户平均消费次数的趋势
df.groupby('month').order_amount.mean().plot()#可能还要考虑用户相同的情况
<matplotlib.axes._subplots.AxesSubplot at 0x2281582eb00>

[外链图片转存失败(img-ZfOGSWZ8-1567614745666)(output_24_1.png)]

2.用户个体消费分析

  • 用户消费金额,消费次数的描述统计
  • 用户消费金额和消费次数的散点图
  • 用户消费金额的分布图
  • 用户消费次数的分布图(二八分布)
  • 用户累计消费金额占比(百分之多少的用户占百分之多少的消费额),头部用户的多寡,实现运营策略,制定方向
grouped_user = df.groupby('user_id')

grouped_user.sum().describe()
order_productsorder_amount
count23570.00000023570.000000
mean7.122656106.080426
std16.983531240.925195
min1.0000000.000000
25%1.00000019.970000
50%3.00000043.395000
75%7.000000106.475000
max1033.00000013990.930000
  • 用户平均购买了7张CD,但是中位值只有3,说明小部分用户购买了大量的CD
  • 用户平均消费106元,中位数有43,判断同上,有极值干扰(一个人买了很多)
  • 基本上符合一个2-8分布
#使用用户的散点图观察#sum求出每个用户的明细数据,plot函数方法
grouped_user.sum().plot.scatter(x = 'order_amount',y = 'order_products')
grouped_user.sum().query('order_amount <4000').plot.scatter(x = 'order_amount',y = 'order_products')
<matplotlib.axes._subplots.AxesSubplot at 0x2281846c278>

[外链图片转存失败(img-GbIY7NFU-1567614745666)(output_29_1.png)]

[外链图片转存失败(img-v4RcYBMu-1567614745666)(output_29_2.png)]

  • 散点图对极值比较敏感,在开始时可以进行过滤,query(‘order_amount <4000’)
  • 函数时有顺序的,plot.scatter
  • CD 数量和客单价有近似正比的关系,可以说明95%的CD的客单价都是差不多的,单一的产品,可能存在极少的珍藏版CD;
  • 如果店家里有多种品类,如CD机,音乐唱片等,可能呈现扇形的扩散状态
  • 散点图揭示的是一种规律
#分布关系
grouped_user.sum().order_amount.plot.hist(bins = 100)
<matplotlib.axes._subplots.AxesSubplot at 0x2281863ceb8>

[外链图片转存失败(img-GXTx3BdJ-1567614745667)(output_31_1.png)]

从直方图中,用户的消费金额,绝大多数呈现集中趋势,小部分异常值干扰判断,可以用**过滤操作**排除异常
grouped_user.sum().query('order_products<100').order_products.plot.hist(bins = 40)
<matplotlib.axes._subplots.AxesSubplot at 0x228189cff98>

在这里插入图片描述

  • 使用切比雪夫过滤掉异常值,计算95%的数据分布情况,去掉5个均值以外的结果
#升序排列,滚动求和
user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum()/x.sum())#滚动求和
#user_cumsum.order_amount.cumsum()/user_cumsum.order_amount.sum() 
user_cumsum
user_cumsum.reset_index().order_amount.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x22818ab2198>

在这里插入图片描述

按用户消费金额进行升序排列,有图可知50%的用户仅贡献了15%的消费额度,而排名前5000的用户就贡献了60%的消费额(如果运营这60%的用户就可能是效益更高)

3.用户的消费行为

  • 用户第一次消费(收购)–和渠道相关,客单价比较高,用户留存率比较低行业,首购的用户从渠道来,可以拓展运营方式和业务
  • 用户最后一次消费–与用户的流失息息相关
  • 新老客消费比
    • 多少用户仅消费了一次?
    • 每月新客占比?
  • 用户分层
    • RFM
    • 新、老、活跃、回流、流失
  • 用户购买周期(按订单)
    • 用户消费周期描述
    • 用户消费周期分布
  • 用户生命周期(按第一次&最后一次消费)
    • 用户生命周期描述
    • 用户生命周期分布
(1) 用户第一次消费
grouped_user.min().order_dt.value_counts().plot()#最小的时间,第一次购买

在这里插入图片描述

  • 用户第一次购买分布,集中在前三个月
  • 其中,在2月11日至2月15日有一次剧烈的波动(渠道或奖励机制发生了变化)
(2) 用户最后一次消费
grouped_user.max().order_dt.value_counts().plot()#最近一次消费

在这里插入图片描述

  • 用户最后一次购买的分布比第一次分布广
  • 大部分最后一次购买,集中在前三个月,说明有很多用户购买了一次就不再进行购买(在真实的场景中,可能是逐渐的缓慢累加)
  • 随着时间递增,最后一次购买数也在递增,消费呈现流失上升的状况(运营的用户忠诚度下降)
(3)新老客消费比
user_life = grouped_user.order_dt.agg(['min','max'])#第一次消费时间,最后一次消费时间
user_life.head()
minmax
user_id
11997-01-011997-01-01
21997-01-121997-01-12
31997-01-021998-05-28
41997-01-011997-12-12
51997-01-011998-01-03
(user_life['min'] == user_life['max']).value_counts()
#判断新老客户的对比(理性角度多少用户消费消费一次会逐渐降低,流失得越来越多)--多少用户消费一次的时间占比
True     12054
False    11516
dtype: int64
  • 有一半用户,就消费了一次
(4)用户分层 -RFM(用户消费额,用户消费次数,用户最近一次消费)-象限法
①RFM模型分析
rfm = df.pivot_table(index = 'user_id',
              values = ['order_products','order_amount','order_dt'],
              aggfunc = {'order_dt':'max',
                         'order_amount':'sum',
                         'order_products':'sum'})
rfm.head()
order_amountorder_dtorder_products
user_id
111.771997-01-011
289.001997-01-126
3156.461998-05-2816
4100.501997-12-127
5385.611998-01-0329

rfm['R'] = - (rfm.order_dt-rfm.order_dt.max())/np.timedelta64(1,'D')
rfm.rename(columns = {'order_products':'F','order_amount':'M'},inplace = True)
rfm.head()
Morder_dtFR
user_id
111.771997-01-011545.0
289.001997-01-126534.0
3156.461998-05-281633.0
4100.501997-12-127200.0
5385.611998-01-0329178.0
def rfm_func(x):
    level = x.apply(lambda x:'1'if x>= 0 else '0')
    label = level.R +level.F + level.M 
    d = {'111':'重要价值客户',
         '011':'重要保持客户',
         '101':'重要挽留客户',
         '001':'重要发展客户',
         '110':'一般价值客户',
         '010':'一般保持客户',
         '100':'一般挽留客户',
         '000':'一般发展客户',
    }
    result = d[label]
    return result

rfm['label'] = rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(rfm_func,axis =1)
rfm.head()#由于极值得影响,这里得平均值偏高,使结果不太准确,改成中位数等,
#5等分等,人工排除(切比雪夫)

#有价值需发展
#有一段时间没消费,比平均消费频次低,金额高
#最近消费过
#+字符串连接
Morder_dtFRlabel
user_id
111.771997-01-011545.0一般挽留客户
289.001997-01-126534.0一般挽留客户
3156.461998-05-281633.0重要保持客户
4100.501997-12-127200.0一般发展客户
5385.611998-01-0329178.0重要保持客户
rfm.groupby('label').sum()
MFR
label
一般价值客户7181.2865036295.0
一般保持客户19937.45171229448.0
一般发展客户196971.2313977591108.0
一般挽留客户438291.81293466951815.0
重要价值客户167080.8311121358363.0
重要保持客户1592039.62107789517267.0
重要发展客户45785.01202356636.0
重要挽留客户33028.401263114482.0

从RFM分层可知,大部分用户为重要保持用户,这是由于极值的影响,所有RFM的划分标准应该为业务为准

  • 尽量用小部分的用户覆盖大部分的额度
  • 不要为了数据好看划分等级
rfm.loc[rfm.label == '重要价值客户','color'] = 'k'
rfm.loc[rfm.label == '重要保持客户','color'] = 'r'
rfm.loc[rfm.label == '重要发展客户','color'] = 'gold'
rfm.loc[rfm.label == '重要挽留客户','color'] = 'y'
rfm.loc[rfm.label == '一般保持客户','color'] = 'g'
rfm.loc[rfm.label == '一般价值客户','color'] = 'b'
rfm.loc[rfm.label == '一般发展客户','color'] = 'c'
rfm.loc[rfm.label == '一般挽留客户','color'] = 'm'
rfm.plot.scatter('F','R',c = rfm.color)

在这里插入图片描述

rfm.head()
Morder_dtFRlabelcolor
user_id
111.771997-01-011545.0一般挽留客户m
289.001997-01-126534.0一般挽留客户m
3156.461998-05-281633.0重要保持客户r
4100.501997-12-127200.0一般发展客户c
5385.611998-01-0329178.0重要保持客户r
② 用户分层 -用户生命周期相关(新客/老客…)
  • 新用户:第一次消费
  • 活跃用户:一直持续消费
  • 回流:之前没有消费,有一段时间没消费,现在又消费了(时间间隔不定)
  • 流失/不活跃:有一短时间没消费,或者上月消费这月不消费
#数据透视
pivoted_counts = df.pivot_table(index = 'user_id',
               columns = 'month',
               values = 'order_dt',
              aggfunc = 'count').fillna(0)
pivoted_counts.head()
month1997-01-01 00:00:001997-02-01 00:00:001997-03-01 00:00:001997-04-01 00:00:001997-05-01 00:00:001997-06-01 00:00:001997-07-01 00:00:001997-08-01 00:00:001997-09-01 00:00:001997-10-01 00:00:001997-11-01 00:00:001997-12-01 00:00:001998-01-01 00:00:001998-02-01 00:00:001998-03-01 00:00:001998-04-01 00:00:001998-05-01 00:00:001998-06-01 00:00:00
user_id
11.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
22.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
31.00.01.01.00.00.00.00.00.00.02.00.00.00.00.00.01.00.0
42.00.00.00.00.00.00.01.00.00.00.01.00.00.00.00.00.00.0
52.01.00.01.01.01.01.00.01.00.00.02.01.00.00.00.00.00.0
df_purchase = pivoted_counts.applymap(lambda x: 1 if x >0 else 0)
df_purchase.tail()
#简化,在一月内有消费为1,没消费为0
#透视会补上1,2月份的消费情况,为0,实质从3月份开始才生命周期开始,多重判断
month1997-01-01 00:00:001997-02-01 00:00:001997-03-01 00:00:001997-04-01 00:00:001997-05-01 00:00:001997-06-01 00:00:001997-07-01 00:00:001997-08-01 00:00:001997-09-01 00:00:001997-10-01 00:00:001997-11-01 00:00:001997-12-01 00:00:001998-01-01 00:00:001998-02-01 00:00:001998-03-01 00:00:001998-04-01 00:00:001998-05-01 00:00:001998-06-01 00:00:00
user_id
23566001000000000000000
23567001000000000000000
23568001100000000000000
23569001000000000000000
23570001000000000000000
def active_status(data):
    status = []
    for i in range(18):
        
        #若本月没有消费,输入输出的判断,18个月作为一个输入,每个月的状态都判断
        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')
            #之前的状态是0,为首购用户
        else:
            #上个月是不活跃,本月有状态,是回流
            if status[i-1] == 'unactive':
                status.append('return')
            #上月未注册,就是新用户
            elif status[i-1] == 'unreg':
                status.append('new')
            #上月活跃,活跃用户
            else:
                status.append('active')
    return status

代码逻辑
① 若本月没有消费

  • 若之前是未注册,则依旧未未注册
  • 若之前有消费,则为流失/补活跃
  • 其他情况,为未注册

② 若本月有消费

  • 若是第一次消费,则为新用户
  • 如果之前有过消费,则上个月为不活跃,则为回流
  • 如果上个月为未注册,则为新用户
  • 除此之外,为活跃
#表应用
#上个月的状态left join 当前状态,逻辑加减法(业界主流)
purchase_stats = df_purchase.apply(active_status,axis=1)
purchase_stats.head(5) 
purchase_stats_ct = purchase_stats.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
#NaN在之后的计算中不被计算,不希望参与处理
#是默认按照列来计数的吗
#数据的流通和变化,不活跃的用户越来越多,新用户少,回流稳定,得到模型,运营不利等
purchase_stats_ct.fillna(0).T.head()
#对NaN填充,T专列
purchase_stats_ct.fillna(0).T.plot.area()
#填充,转列,面积图,得到每类用户的状态
purchase_stats_ct.fillna(0).T.apply(lambda x:x/x.sum(),axis =1)
#每个月份消费用户的构成(active + new + return)
#回流多:促销好;新增多:市场部门/渠道部门给了
#return/unactive

由表可知,每月的用户消费状态变化

  • 活跃用户,持续消费的用户,对应消费运营的质量
  • 回流用户,之前不消费本月才消费,对应的使唤回运营
  • 不活跃用户,对应流失
(5)用户购买周期(按订单)
order_diff = grouped_user.apply(lambda x:x.order_dt -x.order_dt.shift())#shift,将所有的数据错位,偏移相减
order_diff

user_id       
1        0            NaT
2        1            NaT
         2         0 days
3        3            NaT
         4        87 days
         5         3 days
         6       227 days
         7        10 days
         8       184 days
4        9            NaT
         10       17 days
         11      196 days
         12      132 days
5        13           NaT
         14       13 days
         15       21 days
         16       66 days
         17       50 days
         18       16 days
         19       36 days
         20       55 days
         21       84 days
         22        4 days
         23       22 days
6        24           NaT
7        25           NaT
         26      283 days
         27      162 days
8        28           NaT
         29       43 days
                   ...   
23556    69629    63 days
         69630    98 days
         69631   155 days
23557    69632        NaT
23558    69633        NaT
         69634    54 days
         69635    37 days
         69636   246 days
23559    69637        NaT
         69638    54 days
         69639    40 days
23560    69640        NaT
23561    69641        NaT
         69642   309 days
         69643   121 days
23562    69644        NaT
23563    69645        NaT
         69646   193 days
23564    69647        NaT
         69648    57 days
         69649   193 days
23565    69650        NaT
23566    69651        NaT
23567    69652        NaT
23568    69653        NaT
         69654    11 days
         69655    17 days
23569    69656        NaT
23570    69657        NaT
         69658     1 days
Name: order_dt, Length: 69659, dtype: timedelta64[ns]
df.order_dt.shift().head()#错位函数
0          NaT
1   1997-01-01
2   1997-01-12
3   1997-01-12
4   1997-01-02
Name: order_dt, dtype: datetime64[ns]
df.order_dt.head()#显示前五行
0   1997-01-01
1   1997-01-12
2   1997-01-12
3   1997-01-02
4   1997-03-30
Name: order_dt, dtype: datetime64[ns]
order_diff.describe()#描述错位相减结果
count                      46089
mean     68 days 23:22:13.567662
std      91 days 00:47:33.924168
min              0 days 00:00:00
25%             10 days 00:00:00
50%             31 days 00:00:00
75%             89 days 00:00:00
max            533 days 00:00:00
Name: order_dt, dtype: object
(order_diff/np.timedelta64(1,'D')).hist(bins =20)#去掉单位,排除空值

在这里插入图片描述

user_life = grouped_user.order_dt.agg(['min','max'])#第一次消费时间,最后一次消费时间
(user_life['max'] - user_life['min']).describe()
count                       23570
mean     134 days 20:55:36.987696
std      180 days 13:46:43.039788
min               0 days 00:00:00
25%               0 days 00:00:00
50%               0 days 00:00:00
75%             294 days 00:00:00
max             544 days 00:00:00
dtype: object
((user_life['max'] - user_life['min'])/np.timedelta64(1,'D')).hist(bins =20)#去掉单位,排除空值

在这里插入图片描述

  • 用户的生命周期受只购买一次的用户影响比较厉害(可以排除)
  • 用户均消费134天,中位数仅0天
#提取出一次以上的用户
u_1 = ((user_life['max'] - user_life['min']).reset_index()[0]/np.timedelta64(1,'D'))
u_1[u_1>0].hist(bins = 20)

在这里插入图片描述

(6)复购率和回购率(核心电商相关指标)
  • 复购率
    • 自然月内,购买多次的用户占比
  • 回购率
    • 曾经购买的用户在某一时期内再次购买的占比
pivoted_counts.head()#用户在每个月的消费次数
month1997-01-01 00:00:001997-02-01 00:00:001997-03-01 00:00:001997-04-01 00:00:001997-05-01 00:00:001997-06-01 00:00:001997-07-01 00:00:001997-08-01 00:00:001997-09-01 00:00:001997-10-01 00:00:001997-11-01 00:00:001997-12-01 00:00:001998-01-01 00:00:001998-02-01 00:00:001998-03-01 00:00:001998-04-01 00:00:001998-05-01 00:00:001998-06-01 00:00:00
user_id
11.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
22.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
31.00.01.01.00.00.00.00.00.00.02.00.00.00.00.00.01.00.0
42.00.00.00.00.00.00.01.00.00.00.01.00.00.00.00.00.00.0
52.01.00.01.01.01.01.00.01.00.00.02.01.00.00.00.00.00.0
purchase_r = pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
purchase_r.head()
month1997-01-01 00:00:001997-02-01 00:00:001997-03-01 00:00:001997-04-01 00:00:001997-05-01 00:00:001997-06-01 00:00:001997-07-01 00:00:001997-08-01 00:00:001997-09-01 00:00:001997-10-01 00:00:001997-11-01 00:00:001997-12-01 00:00:001998-01-01 00:00:001998-02-01 00:00:001998-03-01 00:00:001998-04-01 00:00:001998-05-01 00:00:001998-06-01 00:00:00
user_id
10.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
21.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
30.0NaN0.00.0NaNNaNNaNNaNNaNNaN1.0NaNNaNNaNNaNNaN0.0NaN
41.0NaNNaNNaNNaNNaNNaN0.0NaNNaNNaN0.0NaNNaNNaNNaNNaNNaN
51.00.0NaN0.00.00.00.0NaN0.0NaNNaN1.00.0NaNNaNNaNNaNNaN

applymap和apply的差别:

  • apply 用在dataframe上,用于对row或者column进行计算;
  • applymap 用于dataframe上,是元素级别的操作;
  • map (其实是python自带的)用于series上,是元素级别的操作。
    链接: https://www.cnblogs.com/cymwill/p/7577369.html
  • 这个地方是由于使用if条件语句而使用applymap?
(purchase_r.sum()/purchase_r.count()).plot(figsize =(10,4))#复购的用户/总人数,10,4分别为宽和高

在这里插入图片描述

复购率稳定在20%左右,前三个月因为有大量新用户涌入,而这批用户只购买了一次,所有导致复购率降低

df_purchase.head()#1表示本月消费过,0表示本月未消费过
month1997-01-01 00:00:001997-02-01 00:00:001997-03-01 00:00:001997-04-01 00:00:001997-05-01 00:00:001997-06-01 00:00:001997-07-01 00:00:001997-08-01 00:00:001997-09-01 00:00:001997-10-01 00:00:001997-11-01 00:00:001997-12-01 00:00:001998-01-01 00:00:001998-02-01 00:00:001998-03-01 00:00:001998-04-01 00:00:001998-05-01 00:00:001998-06-01 00:00:00
user_id
1100000000000000000
2100000000000000000
3101100000010000010
4100000010001000000
5110111101001100000
def purchase_back(data):
    status = []
    for i in range(17):
        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
    #填充最后一个月,
import pandas as pd
import numpy as np
purchase_b = df_purchase.apply(purchase_back,axis =1)
purchase_b.head(5)
user_id
1    [0, nan, nan, nan, nan, nan, nan, nan, nan, na...
2    [0, nan, nan, nan, nan, nan, nan, nan, nan, na...
3    [0, nan, 1, 0, nan, nan, nan, nan, nan, nan, 0...
4    [0, nan, nan, nan, nan, nan, nan, 0, nan, nan,...
5    [1, 0, nan, 1, 1, 1, 0, nan, 0, nan, nan, 1, 0...
dtype: object
(purchase_b.sum()/purchase_b.count()).plot(figsize =(10,4))
##这个地方怎么回事,为解决画不出图
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值