Python数据分析

Python数据分析

安装Python

......

安装Jupyter Notebook

1.按键盘上的win+R键。

2.输入下面的字符。

bash 复制代码
cmd

3.黑框框就出来呐!

4.然后在黑框框里面

输入代码:

bash 复制代码
pip install notebook

5.检查Jupyter Notebook是否能够正常启动

输入代码:

bash 复制代码
jupyter notebook

一般来说会直接打开你默认的浏览器;没打开你也可以复制这个下面两个框选的网址处的任意一个网址进入 Jupyter Notebook。

6.设置Jupyter Notebook的代码路径

输入代码

bash 复制代码
jupyter notebook --generate-config

在"此电脑"中搜索。

然后发现这个文件。

用记事本打开它。

按下ctrl+F就可以开始查找。查找内容如下:

bash 复制代码
The directory to

先把"#"删掉,然后在''里面加入你喜欢的路径。比如我的是:

bash 复制代码
D:\jupyter notebook file

再次打开jupyter notebook就会发现成功了。

番外:如何建立jupyter notebook的快捷方式

在文件夹里面搜索下文

bash 复制代码
jupyter-notebook.exe

找到之后,右键该文件,找到"发送到",找到"桌面快捷方式"。然后就会发现桌面上已经建立好了!

双击快捷方式之后,就可以直接看见这个黑框框。

而且直接打开jupyter notebook的home界面了。

就很方便!!!

比输入win+r -> cmd -> jupyter notebook要快得多了!

项目1:餐厅订单数据分析

1.认识数据并预处理


总代码

bash 复制代码
# 1.订单表的长度,shape,columns
# 2.统计菜名的平均价格(amounts)
# 3.什么菜最受欢迎
# 4.哪个订单ID点的菜最多
# .....
import pandas as pd
import matplotlib.pyplot as plt

# 1.加载数据
data1 = pd.read_excel('meal_order_detail.xlsx',sheet_name='meal_order_detail1')
data2 = pd.read_excel('meal_order_detail.xlsx',sheet_name='meal_order_detail2')
data3 = pd.read_excel('meal_order_detail.xlsx',sheet_name='meal_order_detail3')
# 2.数据预处理(合并数据,NA等处理),分析数据
data = pd.concat([data1,data2,data3],axis=0) #按照行进行拼接数据
# data.head(5)
data.dropna(axis=1,inplace=True) #按照列删除NA列,并且修改源数据
data.info()

2.最受欢迎的菜并可视化分析


添加代码:

bash 复制代码
plt.rcParams['font.sans-serif'] = 'SimHei' ##设置中文显示
%matplotlib inline

添加 fontsize=16,改变字大小

bash 复制代码
dishes_count.plot(kind='bar',fontsize=16)

添加代码:

bash 复制代码
for x,y in enumerate(dishes_count):
    print(x,y)
    plt.text(x,y+2,y,ha='center',fontsize=12)


总代码

bash 复制代码
import numpy as np
# 统计卖出菜品的平均价格
round(data['amounts'].mean(),2) #方法一:pandas自带函数
round(np.mean(data['amounts']),2) #方法二:numpy函数处理

# 频数统计,什么菜最受欢迎  (对菜名进行频数统计,取最大前10名)
dishes_count = data['dishes_name'].value_counts()[:10]
#print(dishes_count)
# 3.数据可视化matplotlib
plt.rcParams['font.sans-serif'] = 'SimHei' ##设置中文显示
%matplotlib inline
dishes_count.plot(kind='line',color=['r'])
dishes_count.plot(kind='bar',fontsize=16)
for x,y in enumerate(dishes_count):
    print(x,y)
    plt.text(x,y+2,y,ha='center',fontsize=12)

3.订单消费维度分析并可视化

bash 复制代码
# 订单点菜的种类最多(1,1,1  1,2,3)
data_group = data['order_id'].value_counts()[:10]
data_group.plot(kind='bar',fontsize=16)
plt.title("订单点菜的种类Top10")
plt.xlabel("订单ID")
plt.ylabel("点菜种类")
bash 复制代码
# 订单点菜的种类最多(1,1,1  1,2,3)
data_group = data['order_id'].value_counts()[:10]
data_group.plot(kind='bar',fontsize=16)
plt.title("订单点菜的种类Top10")
plt.xlabel("订单ID",fontsize=12)
plt.ylabel("点菜种类",fontsize=12)
bash 复制代码
# 订单点菜的种类最多(1,1,1  1,2,3)
data_group = data['order_id'].value_counts()[:10]
data_group.plot(kind='bar',fontsize=16,color=['r','m','b','y','g'])
plt.title("订单点菜的种类Top10")
plt.xlabel("订单ID",fontsize=12)
plt.ylabel("点菜种类",fontsize=12)
bash 复制代码
# 订单ID点菜数量Top10(分组order_id,counts求和,排序前十)
data['total_amounts'] = data['counts']*data['amounts']  #统计单道菜消费总额
dataGroup = data[['order_id','counts','amounts','total_amounts']].groupby(by='order_id')
Group_sum = dataGroup.sum()  #分组求和
sort_counts = Group_sum.sort_values(by='counts',ascending=False)
sort_counts
bash 复制代码
sort_counts['counts'][:10].plot(kind='bar',fontsize=16)
bash 复制代码
#哪个订单ID吃的钱最多(排序)
sort_total_amounts = Group_sum.sort_values(by='total_amounts',ascending=False)
sort_total_amounts['total_amounts'][:10].plot(kind='bar')
plt.title("消费金额Top10")
plt.xlabel("订单ID")
plt.ylabel("消费金额")
bash 复制代码
#哪个订单ID平均消费最贵
Group_sum['average'] = Group_sum['total_amounts']/Group_sum['counts']
sort_average = Group_sum.sort_values(by='average',ascending=False)
sort_average
bash 复制代码
sort_average['average'][:10].plot(kind='bar')
plt.title("订单消费单价Top10")
plt.xlabel("订单ID")
plt.ylabel("消费单价")

4.日期与时间维度进行点菜量分析

bash 复制代码
#一天当中什么时间段,点菜量比较集中(hour)
data['hourcount'] = 1  # 新列,用作计数器
data['time'] = pd.to_datetime(data['place_order_time'])  # 将时间转成日期类型存储
data['hour'] = data['time'].map(lambda x:x.hour)
gp_by_hour = data.groupby(by='hour').count()['hourcount']
gp_by_hour
bash 复制代码
gp_by_hour.plot(kind='bar')
plt.title("点菜数量与小时的关系图")
plt.xlabel("小时")
plt.ylabel("点菜数量")
bash 复制代码
#哪一天订单数量最多
data['daycount'] = 1
data['day'] = data['time'].map(lambda x:x.day)  #解析出天
gp_by_day = data.groupby(by='day').count()['daycount']
gp_by_day.plot(kind='bar')
plt.title("点菜数量与日期的关系图")
plt.xlabel("8月份日期")
plt.ylabel("点菜数量")
bash 复制代码
#查看星期几人数最多,订单数最多,映射数据到星期
data['weekcount'] = 1
data['weekday'] = data['time'].map(lambda x:x.weekday())
gp_by_weekday = data.groupby(by='weekday').count()['weekcount']
gp_by_weekday.plot(kind='bar')
plt.title("点菜数量与星期的关系图")
plt.xlabel("星期")
plt.ylabel("点菜数量")

5.项目总结

不同维度进行数据分析:

针对订单order id:

什么菜最受欢迎

点菜的种类

点菜的数量

消费金额最大

平均消费

针对时间日期进行分析:

点菜量比较集中的时间

哪一天订餐量最大

星期几就餐人数最多

技术点:

拼接数据:pd.concat([列1,...])

分组进行统计(分组求和)

排序,切片Top10

绘制柱状图走势和高度

项目2:物流行业数据分析

1.需求分析

数据来源:某企业销售的6种商品所对应的送货及用户反馈数据

解决问题:

1、配送服务是否存在问题

2、是否存在尚有潜力的销售区域

3、商品是否存在质量问题

先放结论

1、货品4-西北,货品2-马来西亚两条线路存在较大问题,急需提升时效

2、货品2在华东地区还有较大市场空间,适合加大投入,同时货品2在西北配送时效长,用户拒收率高,从成本角度考虑,应该减少投入

3、货品1、2、4质量存在问题,建议扩大抽检范围,增大质检力度

分析过程如下

一、数据清洗

① 重复值、缺失值、格式调整

② 异常值处理(比如:销售金额存在等于0的,属于异常等)

二、数据规整

比如:增加一项辅助列:月份

三、数据分析并可视化

bash 复制代码
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']='SimHei'  ## 设置中文显示

2.预处理-重复值、缺失值、格式调整

bash 复制代码
#删除重复数据
data.drop_duplicates(keep='first',inplace=True)
data.info()
bash 复制代码
#删除重复数据
data.drop_duplicates(keep='first',inplace=True)
# data.info()
#删除缺失值(na,删除带有na的整行数据,axis=0,how='any'默认值)
data.dropna(axis=0,how='any',inplace=True)
print(data.info())
bash 复制代码
#删除订单行(重复运行会报错,因为第一次已经删除了订单行这一列)
data.drop(columns=['订单行'],inplace=True,axis=1)
print(data.info())
bash 复制代码
#更新索引(drop=True:把原来的索引index列删除,重置index)
data.reset_index(drop=True,inplace=True)
bash 复制代码
data
bash 复制代码
# 取出销售金额列,对每一个数据进行清洗
# 编写自定义过滤函数:删除逗号,转成float,如果是万元则*10000,否则,删除元
bash 复制代码
def data_deal(number):
    if number.find('万元') != -1:#找到带有万元的,取出数字,去掉逗号,转成float,*10000
        number_new = float(number[:number.find('万元')].replace(',',''))*10000
        pass
    else:#找到带有元的,删除元,删除逗号,转成float
        number_new = float(number.replace('元','').replace(',',''))
        pass
    return number_new
data['销售金额'].map(data_deal)
bash 复制代码
data['销售金额'] = data['销售金额'].map(data_deal)
data

3.预处理-异常值处理和偏态分布

bash 复制代码
data.describe()


bash 复制代码
#1.消费金额==0,采用删除方法,因为数据量很小
data = data[data['销售金额']!=0]
data.describe()
#2.销售金额和数量存在严重右偏现象,在电商领域2/8很正常,无需处理。

4.预处理-月份列的数据规整

bash 复制代码
data['销售时间'] = pd.to_datetime(data['销售时间'])
data.info()
bash 复制代码
data['销售时间'] = pd.to_datetime(data['销售时间'])
data['月份'] = data['销售时间'].apply(lambda x:x.month)
data

项目3:用户消费行为数据分析

5.数据分析-货品配送服务分析

bash 复制代码
# 三、数据分析并可视化
# 1、配送服务是否存在问题
# a.月份维度
bash 复制代码
data['货品交货状况'] = data['货品交货状况'].str.strip()
data1 = data.groupby(['月份','货品交货状况']).size()
data1
bash 复制代码
data['货品交货状况'] = data['货品交货状况'].str.strip()
data1 = data.groupby(['月份','货品交货状况']).size().unstack()
data1
bash 复制代码
data['货品交货状况'] = data['货品交货状况'].str.strip()
data1 = data.groupby(['月份','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])
data1
bash 复制代码
data1 = data.groupby(['销售区域','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])
data1
bash 复制代码
# b.消费区域维度
data1 = data.groupby(['销售区域','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])
print(data1.sort_values(by='按时交货率',ascending=False))
# 西北地区存在突出的延时交货问题,急需解决
bash 复制代码
# c.货品维度
data1 = data.groupby(['货品','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])
print(data1.sort_values(by='按时交货率',ascending=False))
# 货品4晚交货情况非常严重,其余货品相对较好
bash 复制代码
# d.货品和销售区域维度
data1 = data.groupby(['货品','销售区域','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])
print(data1.sort_values(by='按时交货率',ascending=False))
# 销售区域:最差在西北地区,货品有1和4,主要是货品4送过较晚导致
# 货品:最差的货品2,主要送往华东和马来西亚,主要是马来西亚的送货较晚导致。

6.数据分析-销售区域潜力分析

bash 复制代码
# 2、是否存在尚有潜力的销售区域
# a.月份维度
data1 = data.groupby(['月份','货品'])['数量'].sum().unstack()
data1
bash 复制代码
# 2、是否存在尚有潜力的销售区域
# a.月份维度
data1 = data.groupby(['月份','货品'])['数量'].sum().unstack()
data1.plot(kind='line')
# 货品2在10月和12月份,销量猛增,原因测有二:1.公司加大营销力度2.开发了新的市场
bash 复制代码
# b.不同区域
data1 = data.groupby(['销售区域','货品'])['数量'].sum().unstack()
data1
# 从销售区域看,每种货品销售区域为1~3个,货品1有三个销售区域,货品2有两个销售区域,其余货品均有1个销售区域
bash 复制代码
# c.月份和区域
data1 = data.groupby(['月份','销售区域','货品'])['数量'].sum().unstack()
data1['货品2']
# 货品2在10,12月份销量猛增,原因主要发生在原有销售区域(华东)
# 同样,分析出在7,8,9,11月份销售数量还有很大提升空间,可以适当加大营销力度

7.数据分析-商品质量分析,项目总结

bash 复制代码
# 3.商品是否存在质量问题
data['货品用户反馈'] = data['货品用户反馈'].str.strip()  #取出首位空格
data1 = data.groupby(['货品','销售区域'])['货品用户反馈'].value_counts().unstack()
data1['拒货率'] = data1['拒货'] / data1.sum(axis=1)
data1['返修率'] = data1['返修'] / data1.sum(axis=1)
data1['合格率'] = data1['质量合格'] / data1.sum(axis=1)
data1.sort_values(['合格率','返修率','拒货率'],ascending=False)
bash 复制代码
# 货品3.6.5合格率均较高,返修率比较低,说明质量还可以
# 货品1.2.4合格率较低,返修率较高,质量存在一定的问题,需要改善
# 货品2在马拉西亚的拒货率最高,同时,在货品2在马拉西亚的按时交货率也非常低。猜测:马来西亚人对送货的时效性要求较高。
# 如果达不到,则往往考虑拒货。
# 考虑到货品2主要在华东地区销售量大,可以考虑增大在华东的投资,适当较小马来西亚的投入。

8.项目介绍,需求分析

9.导入数据,初步分析数据

bash 复制代码
# user_ id:用户ID,order_ dt:购买日期,order_products:购买产品数量,order_ amount:购买金额
# 数据时间:1997年1月~1998年6月用户行为数据,约6万条

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
%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+')  #sep='\s+':匹配任意个空格
df
bash 复制代码
# 导入数据
columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table('CDNOW_master.txt',names=columns,sep='\s+')  #sep='\s+':匹配任意个空格
df.head()
bash 复制代码
df.describe()
# 1.用户平均每笔订单购买2.4个商品,标准差2.3,稍微有点波动,属于正常。
# 然而75%分位数的时候,说明绝大多数订单的购买量都不多,围绕在2~3个产品左右:
# 2.购买金额,反映出大部分订单消费金额集中在中小额,30~45左右
bash 复制代码
df.info()

下面将order_dt类型int转成datetime

10.数据预处理,用户整体消费分析(按月)

bash 复制代码
# 数据预处理
df['order_date'] = pd.to_datetime(df['order_dt'],format='%Y%m%d')
# format参数:按照指定的格式去匹配要转换的数据列。
# %Y:四位的年份1994  %m:两位月份05  %d:两位月份31
# %y:两位年份94  %h:两位小时09  %M:两位分钟15  %s:两位秒
df.info()
bash 复制代码
# 数据预处理
df['order_date'] = pd.to_datetime(df['order_dt'],format='%Y%m%d')
# format参数:按照指定的格式去匹配要转换的数据列。
# %Y:四位的年份1994  %m:两位月份05  %d:两位月份31
# %y:两位年份94  %h:两位小时09  %M:两位分钟15  %s:两位秒
# 将order_date转化成精度为月份的数据列
df['month'] = df['order_date'].values.astype('datetime64[M]')  #[M]:控制转换后的精度
# df.head()
df.info()
bash 复制代码
# 用户整体消费趋势分析(按月份)
# 按月份统计产品购买数量,消费金额,消费次数,消费人数
plt.figure(figsize=(20,15))  #单位是英寸
#  每月的产品购买数量
plt.subplot(221)  #两行两列,占据第一个位置
df.groupby(by='month')['order_products'].sum().plot()  #默认折线图
plt.title('每月的产品购买数量')
# 每月的消费金额
plt.subplot(222)  #两行两列
df.groupby(by='month')['order_amount'].sum().plot()  #默认折线图
plt.title('每月的消费金额')
# 每月的消费次数
plt.subplot(223)  #两行两列
df.groupby(by='month')['user_id'].count().plot()  #默认折线图
plt.title('每月的消费次数')
# 每月的消费人数(根据user_id进行去重统计,在计算个数)
plt.subplot(224)  #两行两列
df.groupby(by='month')['user_id'].apply(lambda x:len(x.drop_duplicates())).plot()  #默认折线图
plt.title('每月的消费人数')
# 分析结果:
# 图一可以看出,前三个月销量非常高,而以后销量较为稳定,并且稍微呈现下降趋势
# 图二可以看出、依然前三个月消费金额较高,与消费数量成正比例关系,三月份过后下降严重,并呈现下降趋势,思考原因?1:跟月份有关
# 在我国来1,2,3月份处于春节前后。2.公司在1,2,3,月份的时候是否加大了促销力度
# 图三可以看出,前三个月订单数在10080左右,后续月份的平均消费单数在2500左右
# 图四可以看出,前三个月消费人数在8000~100ee左右,后续平均消费消费在2000不到的样子
# 总结:所有数据显示,97年前三月消费事态异常,后续趋于常态化

11.用户个体消费分析-消费金额与次数描述统计

bash 复制代码
# 用户个体消费分析
# 1.用户消费金额,消费次数(产品数量)描述统计

# 选择 df 中所有数值类型的列
# select_dtypes 方法用于根据数据类型选择列
# include 参数设置为 [np.number] 表示只包括数值类型的列(整数和浮点数)
# columns 属性返回选择列的名称列表
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
# 对数值型列进行按 'user_id' 分组,并计算每组的总和
# groupby 方法用于根据一个或多个键,进行分组
# sum 方法对分组后的每个组应用求和操作
# 这里我们先通过 [numeric_cols] 选择数值型列,然后对这些列进行分组求和
user_grouped = df[numeric_cols].groupby('user_id').sum()
# 打印分组求和结果的描述性统计信息
# describe 方法返回描述性统计信息,如 count, mean, std, min, 25%, 50%, 75%, max
# 这里只对数值型列有效
print(user_grouped.describe())
# 打印用户的数量,即 'user_id' 分组后的唯一值的数量
# len 函数返回行数,即不同 'user_id' 的数量
print('用户数量:',len(user_grouped))
# 从用户的角度:用户数量23570个,每个用户平均购买7个cD,但是中位数只有3,
# 并且最大购买量为1033,平均值大于中位数,属于典型的右偏分布(替购买量<7的用户背锅)
# 从消费金额角度:平均用户消费106,中位数43,并且存在士豪用户1399,结合分位数和最大值来看,平均数与75%分位数几乎相等,
# 属于典型的右偏分布,说明存在小部分用户(后面的25%)高额消费(这些用户需要给消费金额<106的用户背锅,只有这样才能使平均数维持在106)
bash 复制代码
# 绘制每个用户的产品的购买量与消费金额散点图
df.plot(kind='scatter',x='order_products',y='order_amount')
# 从图中可知,用户的消费金额与购买量呈现线性趋势,每个商品均价15左右
# 订单的极值点比较少(消费金额>1000,或者购买量大于60),对于样本来说影响不大,可以忽略不记
bash 复制代码
amount_total = user_cumsum['amount_cumsum'].max()  #消费金额总值
user_cumsum['prop'] = user_cumsum.apply(lambda x:x['amount_cumsum']/amount_total,axis=1)  #前xx名用户的总贡献率
user_cumsum.tail()
bash 复制代码
user_cumsum['prop'].plot()
# 由图分析可知,前20000名用户贡献总金额的40%剩余3500名用户贡献了60%。(2/8原则)

12.用户个体消费分析-首购和最后一次购买分析

bash 复制代码
# 用户消费行为
# 用户分组,取最小值,即为收购时间
# A 1997-1-1
# B 1997-1-1
df.groupby(by='user_id')['order_date'].min()
bash 复制代码
df.groupby(by='user_id')['order_date'].min().value_counts().plot()
# 由图可知,首次购买的用户量在1月1号~2月10号呈明显上升趋势,后续开始逐步下降,猜测:有可能是公司产品的推广力度或者价格所致
bash 复制代码
df.groupby(by='user_id')['order_date'].max().value_counts().plot()
# 大多数用户最后一次购买时间集中在前3个月,说明缺少忠诚用户。
# 随着时间的推移,最后一次购买商品的用户量呈现上升趋势,猜测:这份数据选择是的前三个月消费的用户在后面18个月的跟踪记录

13.用户分层-透视表与构建RFM模型

构建RFM模型

  • 为了进行精细化运营,可以利用RFM模型对用户价值指数(衡量历史到当前用户贡献的收益)进行计算,其中
  • R:(Recency,最近一次消费),R值越大,表示客户交易发生的日期越久,反之则交易发生的日期越近
  • F:(Frequency,消费频率),F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃(此处我们选择购买产品数量作F)
  • M:(Monetary,消费金额),M值越大,表示客户值越高,反之则表示客户价值越低

根据上述三个维度,对客户做细分

透视表是一种可以对数据动态排布并且分类汇总的表格格式。或许大多数人都在Excel使用过数据透视表,也体会到它的强大功能,而在pandas中它被称作pivot table。

为什么要使用pivot table?

  • 灵活性高,可以随意定制你的分析计算要求
  • 脉络清晰易于理解数据
  • 操作性强,报表神器
bash 复制代码
# 用户分层
# 1.构建RFM模型
# 透视表的使用(index:相当于groupby,values:去除的数据列,aggfunc:key值必须存在于values列中,并且必须跟随有效的聚合函数
rfm = df.pivot_table(index='user_id',
                     values=['order_products','order_amount','order_date'],
                     aggfunc={
                         'order_date':'max',  #最后一次购买
                         'order_products':'sum',  #购买产品的总数量
                         'order_amount':'sum'  #消费总金额
                     })
rfm.head()
bash 复制代码
# 用每个用户的最后一次购买时间-日期列中的最大值,最后再转换成天数,小数保留一位
rfm['R'] = -(rfm['order_date']-rfm['order_date'].max())/np.timedelta64(1,'D')  #取相差的天数,保留一位小数
rfm.rename(columns={'order_products':'F','order_amount':'M'},inplace=True)
rfm.head()

14.用户分层-RFM模型分析并可视化

bash 复制代码
# RFM计算方式:每一列数据减去数据所在列的平均值,有正有负,根据结果值与1做比较,如果>=1,设置为,否则
# rfm['R']-rfm['R'].mean()
def rfm_func(x):  #x:分别代表每一列数据
    level = x.apply(lambda x:'1' if x>=1 else '0')
    label = level['R'] + level['F'] + level['M']  #举例:100   001
    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()
bash 复制代码
#客服分层可视化
for label,grouped in rfm.groupby(by='label'):
    print(label,grouped)
bash 复制代码
#客服分层可视化
for label,grouped in rfm.groupby(by='label'):
    # print(label,grouped)
    x = grouped['F']
    y = grouped['R']
    plt.scatter(x,y,label=label)
plt.legend()  #显示图例
plt.xlabel('F')
plt.ylabel('R')

15.用户分层-新用户,活跃用户,回流用户的流失分析

新老,活跃,回流用户分析

  • 新用户的定义是第一次消费。
  • 活跃用户即老客,在某、个时间窗口内有过消费
  • 不活跃用户则是时间窗口内没有消费过的老客。
  • 回流用户:相当于回头客的意思。
  • 用户回流的动作可以分为自主回流与人工回流,自主回流指玩家自己回流了,而人工回流则是人为参与导致的。
bash 复制代码
pivoted_counts = df.pivot_table(
    index='user_id',
    columns='month',
    values='order_dt',
    aggfunc='count'
)
pivoted_counts
bash 复制代码
pivoted_counts = df.pivot_table(
    index='user_id',
    columns='month',
    values='order_dt',
    aggfunc='count'
).fillna(0)
pivoted_counts
bash 复制代码
# 由于浮点数不直观,并且需要转成是否消费过即可,用0、1表示
df_purchase = pivoted_counts.applymap(lambda x:1 if x>0 else 0)
# apply:作用与dataframe数据中的一行或者一列数据
# applymap:作用与dataframe数据中的每一个元素
# map:本身是一个series的函数,在df结构中无法使用map函数,map函数作用于series中每一个元素的
df_purchase.head()
bash 复制代码
def active_status(data):  #data:整行数据,共18列
    status = []  #负责存储18个月的状态:unreg|new|active|unactive|return
    for i in range(18):
        # 本月没有消费
        if data[i] == 0:
            if len(status) == 0:  #前面没有任何记录(97年1月份)
                status.append('unreg')
            else:  #开始判断上一个状态
                if status[i-1] == 'unreg':  #一直为消费过
                    status.append('unreg')
                else:#new|active|unactive|return
                    status.append('unactive')  #不管上个月是否消费过,本月都是不活跃用户
        #本月有消费==1
        else:
            if len(status) == 0:#前面没有任何记录(97年1月份)
                status.append('new')  #第一次消费
            else:
                if status[i-1] == 'unactive':
                    status.append('return')
                elif status[i-1] == 'unreg':
                    status.append('new')  #第一次消费
                else:#new|active|return=1
                    status.append('active')
    return pd.Series(status,df_purchase.columns)  #值status,列名df_purchase中的列名
purchase_states = df_purchase.apply(active_status,axis=1)  #得到用户名分层结果
purchase_states.head()
bash 复制代码
# 用Nan替换unreg
purchase_states_ct = purchase_states.replace('unreg',np.NaN)
purchase_states_ct.head(60)
bash 复制代码
# 用Nan替换unreg
purchase_states_ct = purchase_states.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
purchase_states_ct.head(60)
bash 复制代码
purchase_states_ct.T.fillna(0).plot.area()  #行列变换
# 前三个月可知,红色活跃用户和蓝色新用户,占比较大
# 四月份过后,新用户和活跃用户,开始下降,并且呈现稳定趋势
# 回流用户主要产生在4月过后,呈现稳定趋势,是网站的重要客户
bash 复制代码
# 回流用户的占比
purchase_states_ct.T.fillna(0)
bash 复制代码
# 回流用户的占比
rate = purchase_states_ct.T.fillna(0).apply(lambda x : x/x.sum(),axis=1)
rate
bash 复制代码
# 回流用户的占比
rate = purchase_states_ct.T.fillna(0).apply(lambda x : x/x.sum(),axis=1)
# rate
plt.plot(rate['return'],label='return')
plt.legend()
bash 复制代码
# 回流用户的占比
rate = purchase_states_ct.T.fillna(0).apply(lambda x : x/x.sum(),axis=1)
# rate
plt.plot(rate['return'],label='return')
plt.plot(rate['active'],label='active')
plt.legend()
# 回流用户:前五个月,回流用户上涨,过后呈现下降趋势,平均维持在5%比例
# 活跃用户:前三个月活跃用户大量增长,猜测由于活到新引来很多新用户所导致,5月份过后开始下降,平均维持在2.5%左右
# 网站运营稳定后,回流用户占比大于活跃用户

16.用户购买周期分析

bash 复制代码
# shift函数:将数据移动到一定的位置
data1 = pd.DataFrame({
    'a':[0,1,2,3,4,5],
    'b':[5,4,3,2,1,0]
})
data1
bash 复制代码
# shift函数:将数据移动到一定的位置
data1 = pd.DataFrame({
    'a':[0,1,2,3,4,5],
    'b':[5,4,3,2,1,0]
})
data1.shift()
bash 复制代码
# shift函数:将数据移动到一定的位置
data1 = pd.DataFrame({
    'a':[0,1,2,3,4,5],
    'b':[5,4,3,2,1,0]
})
data1.shift(axis=0)  #整体向下移动一个位置(默认值:axis=0)

同效果

bash 复制代码
# shift函数:将数据移动到一定的位置
data1 = pd.DataFrame({
    'a':[0,1,2,3,4,5],
    'b':[5,4,3,2,1,0]
})
data1.shift(axis=0)  #整体向下移动一个位置(默认值:axis=0)
data1.shift(axis=1)
bash 复制代码
# 计算购买日期(购买日期的时间差值)
order_diff = df.groupby(by='user_id').apply(lambda x:x['order_date']-x['order_date'].shift())  #当前订单日期-上一次订单日期
order_diff.describe()
bash 复制代码
(order_diff/np.timedelta64(1,'D')).hist(bins=20)  #影响柱子的高度,每个柱子的宽度=(最大值-最小值)/bins
# 得知:平均消费周期为68天
# 大多数用户消费周期低于100天
# 呈现典型的长尾分布,只有小部分用户消费周期在200天以上(不积极消费的用户),可以在这批用户消费后3天左右进行电话回访或短信
# 赠送优惠券等活动,增大消费频率

17.用户生命周期分析

bash 复制代码
# 计算方式:用户最后一次购买日期(max)-第一次购买的日期(min)。如果差值==0,说明用户仅仅购买了一次
df.groupby('user_id')['order_date'].agg(['min','max'])
bash 复制代码
# 计算方式:用户最后一次购买日期(max)-第一次购买的日期(min)。如果差值==0,说明用户仅仅购买了一次
user_life = df.groupby('user_id')['order_date'].agg(['min','max'])
(user_life['max']==user_life['min']).value_counts().plot.pie(autopct='%1.1f%%')  #格式化成1位小数
plt.legend(['仅消费一次','多次消费'])
# 一半以上的用户仅仅消费了一次,说明运营不利,留存率不好
bash 复制代码
# 生命周期分析
(user_life['max']-user_life['min']).describe()  #生命周期分析
# 用户平均生命周期为134天,但是中位数==0,再次验证大多数用户消费了一次,低质量用户
# 75%分位数以后的用户,生命周期>294天,属于核心用户,需要着重维持。
# 前三个月的新用户数据,所以分析的是这些用户的生命周期
bash 复制代码
# 绘制所有用户生命周期直方图+多次消费
plt.figure(figure=(12,6))
plt.subplot(121)
((user_life['max']-user_life['min'])/np.timedelta64(1,'D')).hist(bins=15)
plt.title('所有用户生命周期直方图')
plt.xlabel('生命周期天数')
plt.ylabel('用户人数')
bash 复制代码
(user_life['max']-user_life['min']).reset_index()
bash 复制代码
(user_life['max']-user_life['min']).reset_index()[0]/np.timedelta64(1,'D')
bash 复制代码
plt.subplot(122)
u_1= (user_life['max']-user_life['min']).reset_index()[0]/np.timedelta64(1,'D')
u_1[u_1>0].hist(bins=15)
plt.title('多次消费的用户生命周期直方图')
plt.xlabel('生命周期天数')
plt.ylabel('用户人数')
# 对比可知,第二幅图过滤掉了生命周期==0的用户,呈现双峰结构
# 虽然二图中还有一部分用户的生命周期趋于8天,但是比第一幅图好了很多,虽然进行了多次消费,但是不成长期来消费,属于普通用户,可针对性进行营销推广活动
# 少部分用户生命周期集中在380~500天,属于我们的忠诚客户,需要大力度维护此类客户

18.用户复购率分析

bash 复制代码
# 复购率分析
# 计算方式:在自然月内,购买多次的用户在总消费人数中的占比(若客户在同一天消费了多次,也称之复购用户)
# 消费者有三种:消费记录>=2次的:消费中人数;本月无消费用户;
# 复购用户:1  非复购的消费用户:0  自然月没有消费记录的用户:NAN
purchase_r = pivoted_counts.applymap(lambda x:1 if x>1 else np.NAN if x==0 else 0)
purchase_r.head()
bash 复制代码
# 计算方式:在自然月内,购买多次的用户在总消费人数中的占比(若客户在同一天消费了多次,也称之复购用户)
# 消费者有三种:消费记录>=2次的:消费中人数;本月无消费用户;
# 复购用户:1  非复购的消费用户:0  自然月没有消费记录的用户:NAN(不参与count计数)
purchase_r = pivoted_counts.applymap(lambda x:1 if x>1 else np.NAN if x==0 else 0)
purchase_r.head()
# purchase_r.sum() 求出复购用户
# purchase_r.count()  求出所有参与购物的用户(NAN不参与计数)
purchase_r.sum()/purchase_r.count()
bash 复制代码
(purchase_r.sum()/purchase_r.count()).plot(figsize=(12,6))
# 前三个月复购率开始上升,后续趋于平稳维持在20%~22%之间。
# 分析前三个月复购率低的原因,可能是因为大批新用户仅仅购买一次造成的。

19.用户回购率分析

bash 复制代码
# 回购率分析
# 计算方式:在一个时间窗口内进行了消费,在下一个窗口内又进行了消费
def purchase_back(data):
    status = []  #存储用户回购率状态
    #1:回购用户  0:非回购用户(当前月消费了,下个未消费)  NaN:当前月份未消费
    for i in range(17):
        #当前月份消费了
        if data[i] == 1:
            if data[i+1]== 1:
                status.append(1)  #回购用户
            elif data[i+1] == 0:  #下个月未消费
                status.append(0)
        else:  #当前月份未进行消费
            status.append(np.NaN)
    status.append(np.NaN)
    return pd.Series(status,df_purchase.columns)
purchase_b = df_purchase.apply(purchase_back,axis=1)
purchase_b.head()
bash 复制代码
# 回购率
plt.figure(figsize=(20,4))
plt.subplot(211)
# 回购率
(purchase_b.sum() / purchase_b.count()).plot(label='回购率')
bash 复制代码
# 回购率
plt.figure(figsize=(20,4))
plt.subplot(211)
# 回购率
(purchase_b.sum() / purchase_b.count()).plot(label='回购率')
# 复购率
(purchase_r.sum() / purchase_r.count()).plot(label='复购率')
plt.legend()
plt.ylabel('百分比%')
plt.title('用户回购率和复购率对比图')
bash 复制代码
# 回购率
plt.figure(figsize=(20,4))
plt.subplot(211)
# 回购率
(purchase_b.sum() / purchase_b.count()).plot(label='回购率')
# 复购率
(purchase_r.sum() / purchase_r.count()).plot(label='复购率')
plt.legend()
plt.ylabel('百分比%')
plt.title('用户回购率和复购率对比图')
# 回购率可知,平稳后在30%左右,波形性稍微较大
# 复购率低于回购率,平稳后在20%左右,波动小较小
# 前三个月不困是回购还是复购,都呈现上升趋势,说明新用户需要一定时间来变成复购或者回购用户
# 结合新老用户分析,新客户忠诚度远低于老客户忠诚度。

# 回购人数与购物总人数
plt.subplot(212)
plt.plot(purchase_b.sum(),label='回购人数')
plt.plot(purchase_b.count(),label='购物总人数')
plt.xlabel('month')
plt.ylabel('人数')
plt.legend()
# 前三个月购物总人数远远大于回购人数,主要是因为很多新用户在1月份进了首次购买
# 三个月后,回购人数和购物总数开始稳定,回购人数稳定在1800左右,购物总人数在2800左右

20.项目总结

1.整体趋势:按年的月份趋势销量和销售额在1-3月份相对极高,然后骤降,原因可能跟这段时间的大力促销或与商品的季度属性有关。

2.用户个体特征:每笔订单的金额和商品购买量都集中在区间的低段水平,都是小金额小批量进行购买,此类交易群体,可在丰富产品线和增加促销活动提高转换率和购买率。

3.大部分用户的消费总额和购买总量都集中刚在低段,长尾分布,这个跟用户需求有关,可以对商品进行多元文化价值的赋子,增强其社交价值属性,提高用户的价值需求。

4.用户的消费周期:有二次以上消费的用户,平均68天,所以在50天到60天期间,应该对这批用户进行刺激召回,细致点,比如10天回复满意度,30天发放优惠券,55天的时候提醒优惠券的使用。

5.用户的生命周期:有二次及以上消费的用户的平均生命周期是276天。用户的生命周期分别在20天内与400至500天间,应该在20天内对客户进行引导,促进其再次消费并形成消费习惯,延长其生命周期;在100至400天的用户,也要根据其特点推出有针对性的营销活动,引导其持续消费。

6.新客户的复购率约为12%,老客户的复购率在20%左右;新客户的回购率在15%左右,老客户的回购率在30%左右,需要营销策略积极引导其再次消费及持续消费。

7.用户质量:用户个体消费有一定规律性,大部分用户的消费集中在2000以下,用户消费反应了2/8法则,消费排名前20%的用户贡献了80%的消费额。所以说,狠抓高质量用户是万古不变的道理,这些高质量客户都是"会员"类型,需要专门为会员优化购物体验,比如专线接听、特殊优惠等等。

方法总结:

1.针对用户进行按照月份做整体和个体分析,主要分析维度是人数,消费金额,购买量

2.消费分析:首购时间,最后一次购买时间,相邻两个购物时间的间隔,用户分层(RFM模型+数据透视表),分析维度主要是新用户,活跃用户,不活跃用户流失分析,回流用户占比

3.复购率和回购率进行分析

项目4:KLOOK旅游数据分析

1.背景介绍

KLOOK简介

客路旅行(KLOOK)是一家专注于境外旅游资源整合的在线旅行平台,提供景点门票、一日游、特色体验、当地交通与美食预订服务 。业务覆盖全球25个国家及地区。KLOOK客路旅行总部设立于香港,团队已遍布全球20个城市,团队成员人数达千人,分别来自超过25个国家及地区。

2019年在线旅游独角兽4家,估值分别为:

  • 马蜂窝(20亿美元)
  • 客路旅行(13.5亿美元)
  • 驴妈妈(12.6亿美元)
  • 要出发(10.77亿美元)

任务目标

(1)分析KLOOK客路旅行《台北101观景台》的门票售卖数据,2016年到2019年,通过该活动侧面分析KLOOK客路旅行的经营状况及面临的风险。

(2)通过案例数据完成一份Python的数据分析报告。

2.每天每月销量分析

相关推荐
家有狸花1 分钟前
PYTHON自学笔记(一)vscode配置
笔记·vscode·python
鸽芷咕26 分钟前
【python学习】快速了解python基本数据类型
开发语言·python·学习
秋刀鱼_(:з」∠)_别急30 分钟前
如何获取歌曲id---cloudmusic
后端·爬虫·python·计算机网络·ajax·okhttp·xhr
杰哥在此37 分钟前
Python面试题:如何在 Python 中读取和写入 JSON 文件?
开发语言·python·面试·json·编程
我是陈泽41 分钟前
AI教你如何系统的学习Python
开发语言·数据结构·人工智能·python·学习·青少年编程
落798.1 小时前
【植物大战僵尸杂交版】获取+存档插件
python·游戏·github
yukai080081 小时前
Python 全栈系列258 线程并发与协程并发
python·microsoft·性能优化
alim20122 小时前
python语句性能分析
开发语言·python
2402_857583492 小时前
深入探索:scikit-learn中递归特征消除(RFE)的奥秘
python·机器学习·scikit-learn
范范08252 小时前
探索Sklearn:从数据预处理到模型评估
人工智能·python·sklearn