
知道什么是透视表
掌握Pandas透视表(pivot_table)的使用方法
视频教程学习地址:Pandas透视表(pivot_table)的使用方法
数据透视表(Pivot Table)是一种交互式的表,可以进行某些计算,如求和与计数等。所进行的计算与数据跟数据透视表中的排列有关。
之所以称为数据透视表,是因为可以动态地改变它们的版面布置,以便按照不同方式分析数据,也可以重新安排行号、列标和页字段。每一次改变版面布置时,数据透视表会立即按照新的布置重新计算数据。另外,如果原始数据发生更改,则可以更新数据透视表。
在使用Excel做数据分析时,透视表是很常用的功能,Pandas也提供了透视表功能,对应的API为pivot_table
Pandas pivot_table函数介绍:pandas有两个pivot_table函数
pandas.pivot_table
pandas.DataFrame.pivot_table
pandas.pivot_table 比 pandas.DataFrame.pivot_table 多了一个参数data,data就是一个dataframe,实际上这两个函数相同
pivot_table参数中最重要的四个参数 values,index,columns,aggfunc,下面通过案例介绍pivot_tabe的使用
业务背景介绍
某女鞋连锁零售企业,当前业务以线下门店为主,线上销售为辅 通过对会员的注册数据以及的分析,监控会员运营情况,为后续会员运营提供决策依据 会员等级说明 ① 白银: 注册(0) ② 黄金: 下单(1~3888) ③ 铂金: 3888~6888 ④ 钻石: 6888以上
数据分析要达成的目标
描述性数据分析 使用业务数据,分析出会员运营的基本情况
案例中用到的数据
① 会员信息查询.xlsx ② 会员消费报表.xlsx ③ 门店信息表.xlsx ④ 全国销售订单数量表.xlsx
分析会员运营的基本情况
从量的角度分析会员运营情况: ① 整体会员运营情况(存量,增量) ② 不同渠道(线上,线下)的会员运营情况 ③ 线下业务,拆解到不同的地区、门店会员运营情况 从质的角度分析会员运营情况: ① 会销比 ② 连带率 ③ 复购率
每月存量,增量是最基本的指标,通过会员数量考察会员运营情况
用到的数据:会员信息查询.xlsx
import pandas as pd
custom_info=pd.read_excel('data/会员信息查询.xlsx')
custom_info.info() 显示结果:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 952714 entries, 0 to 952713
Data columns (total 12 columns):
会员卡号 952714 non-null object
会员等级 952714 non-null object
会员来源 952714 non-null object
注册时间 952714 non-null datetime64[ns]
所属店铺编码 952714 non-null object
门店店员编码 253828 non-null object
省份 264801 non-null object
城市 264758 non-null object
性别 952714 non-null object
生日 785590 non-null object
年齡 952705 non-null float64
生命级别 952714 non-null object
dtypes: datetime64[ns](1), float64(1), object(10)
memory usage: 87.2+ MB
#会员信息查询
custom_info.head() 显示结果:

需要按月统计注册的会员数量,注册时间原始数据需要处理成年-月的形式
# 给 会员信息表 添加年月列
from datetime import datetime
custom_info.loc[:,'注册年月'] = custom_info['注册时间'].apply(lambda x : x.strftime('%Y-%m'))
custom_info[['会员卡号','会员等级','会员来源','注册时间','注册年月']].head() 显示结果:

month_count = custom_info.groupby('注册年月')[['会员卡号']].count()
month_count.columns = ['月增量']
month_count.head() 显示结果:

用数据透视表实现相同功能:dataframe.pivot_table()
index:行索引,传入原始数据的列名 原始数据的哪一个列作为新生成df中行索引
columns:列索引,传入原始数据的列名 原始数据的哪一个列作为新生成df中列名
values: 要做聚合操作的列名
aggfunc:聚合函数
custom_info.pivot_table(index = '注册年月',values = '会员卡号',aggfunc = 'count') 显示结果:

计算存量 cumsum 对某一列 做累积求和 1 1+2 1+2+3 1+2+3+4 ...
#通过cumsum 对月增量做累积求和
month_count.loc[:,'存量'] = month_count['月增量'].cumsum()
month_count 显示结果:

可视化,需要去除第一个月数据,第一个月数据是之前所有会员数量的累积(数据质量问题)
#Pandas版本>1.1
import matplotlib.pyplot as plt
month_count['月增量'].plot(figsize = (20,8),color='red',secondary_y = True)
month_count['存量'].plot.bar(figsize = (20,8),color='gray',xlabel = '年月',legend = True,ylabel = '存量')
plt.title("会员存量增量分析",fontsize=20) 显示结果:

会员增量存量不能真实反映会员运营的质量,需要对会员的增量存量数据做进一步拆解
从哪些维度来拆解?
从指标构成来拆解:会员 = 白银会员+黄金会员+铂金会员+钻石会员
从业务流程来拆解:当前案例,业务分线上、线下,又可以进一步拆解:按大区,按门店
会员等级分布分析的目的和要分析的指标
会员按照等级拆解分为:
① 白银: 注册(0) ② 黄金: 下单(1~3888) ③ 铂金: 3888~6888 ④ 钻石: 6888以上
由于会员等级跟消费金额挂钩,所以会员等级分布分析可以说明会员的质量
通过groupby实现,注册年月,会员等级,按这两个字段分组,对任意字段计数
month_degree_count =custom_info.groupby(['注册年月','会员等级'])[['会员卡号']].count()
month_degree_count 显示结果:

80 rows × 1 columns
分组之后得到的是multiIndex类型的索引,将multiIndex索引变成普通索引
#使用reset_index()
month_degree_count.reset_index() 显示结果:

80 rows × 3 columns
#使用unstack()
month_degree_count.unstack() 显示结果:

使用透视表实现
member_rating = custom_info.pivot_table(index = '注册年月',columns='会员等级',values='会员卡号',aggfunc = 'count')
member_rating 显示结果:

#去掉首月数据
member_rating=member_rating[1:] pandas绘制图表
member_rating = member_rating[1:] # 去掉第一个月的异常数据
## 画图显示增量等级
fig, ax1 = plt.subplots(figsize=(20, 8), dpi=100)
ax2 = ax1.twinx()
member_rating[['白银会员', '黄金会员']].plot.bar(ax=ax1, rot=0, grid=True, xlabel='年月',ylabel = '白银黄金')
ax1.legend(loc='upper left')
member_rating[['钻石会员', '铂金会员']].plot(ax=ax2, color=['red', 'gray'], ylabel='铂金钻石')
ax2.legend(loc='upper right') # loc参数 可以设置不同位置ax2.legend(loc='upper/bottom left/center/right')
plt.title('会员增量等级分布', fontsize= 20) 显示结果:

增量等级占比分析,查看增量会员的消费情况
#按行求和
member_rating.loc[:,'总计'] = member_rating.sum(axis = 'columns')
#计算白银和黄金会员等级占比 铂金钻石会员数量太少暂不计算
member_rating.loc[:,'白银会员占比'] = member_rating['白银会员'].div(member_rating['总计'])
member_rating.loc[:,'黄金会员占比'] = member_rating['黄金会员'].div(member_rating['总计'])
member_rating 显示结果:

绘图
member_rating[['白银会员占比','黄金会员占比']].plot(color=['r','g'],ylabel='占比',figsize=(16,8),grid=True)
plt.title("会员等级占比分析",fontsize=20) 显示结果:

计算各个等级会员占整体的百分比
思路:按照会员等级分组,计算每组的会员数量,用每组会员数量/全部会员数量
#会员按等级分组groupby实现
ratio = custom_info.groupby('会员等级')[['会员卡号']].count()
#另一种写法
custom_info.groupby('会员等级').agg({'会员卡号':'count'})
#会员按等级分组透视表实现
ratio = custom_info.pivot_table(index = '会员等级',values = '会员卡号',aggfunc = 'count') 显示结果:

# 计算占比
ratio.columns=['会员数']
ratio.loc[:,'占比'] = ratio['会员数'].div(ratio['会员数'].sum())
ratio 显示结果:

报表可视化
# autopct 显示数据标签,并指定保留小数位数
ratio.loc[['白银会员','钻石会员','黄金会员','铂金会员'],'占比'].plot.pie(figsize=(16,8),autopct='%.1f%%',fontsize=16) 显示结果:

从业务角度,将会员数据拆分成线上和线下,比较每月线上线下会员的运营情况
将“会员来源”字段进行拆解,统计线上线下会员增量
#按会员来源进行分组 使用groupby实现
from_data = custom_info.groupby(['注册年月','会员来源'])[['会员卡号']].count()
from_data = from_data.unstack()
from_data.columns = ['电商入口', '线下扫码']
from_data = from_data[1:]
from_data 显示结果:

# 透视表实现
custom_info.pivot_table(index = ['注册年月'],columns='会员来源',values ='会员卡号',aggfunc = 'count') 可视化
from_data.plot(figsize=(20,8),fontsize=16,grid=True)
plt.title("电商与线下会员增量分析",fontsize=18) 显示结果:

会员信息查询表中,只有店铺信息,没有地区信息,需要从门店信息表中关联地区信息
#查看门店信息表
store_info = pd.read_excel('data/门店信息表.XLSX')
store_info 显示结果:

只需要用到门店信息表中的[['店铺代码','地区编码']] 两列
store_info[['店铺代码','地区编码']].head() 显示结果:

使用custom_info与store_info 关联,将地区编码添加到custom_info中
custom_info1 = pd.merge(custom_info,store_info[['店铺代码','地区编码']],left_on='所属店铺编码',right_on='店铺代码') 显示结果:

#统计不同地区的会员数量 注意只统计线下,不统计电商渠道 GBL6D01为电商
district = custom_info1[custom_info1['地区编码']!='GBL6D01'].groupby('地区编码')[['会员卡号']].count()
#修改列名
district.columns = ['会员数量']
district 显示结果:

district['店铺数'] = custom_info1[['地区编码','所属店铺编码']].drop_duplicates().groupby('地区编码')['所属店铺编码'].count()
district 显示结果:

district.loc[:,'每店平均会员数']=round(district['会员数量'].div(district['店铺数']))
#计算总体平均数
district.loc[:,'总平均会员数']=district['会员数量'].sum()/district['店铺数'].sum()
#排序
district=district.sort_values(by='每店平均会员数',ascending=False)
district.head() 显示结果:

数据可视化
district['每店平均会员数'].plot.bar(figsize=(20,8),color='r',legend = True,grid=True)
district['总平均会员数'].plot(figsize=(20,8),color='g',legend = True,grid=True)
plt.title("地区店均会员分析",fontsize=18) 显示结果:

会销比的计算和分析会销比的作用
会销比 = 会员消费的金额 / 全部客户消费的金额
由于数据脱敏的原因,没有全部客户消费金额的数据,所以用如下方式替换
会销比 = 会员消费的订单数 / 全部销售订单数
会销比统计的是会员消费占所有销售金额的比例
通过会销比可以衡量会员的整体质量
加载数据
custom_consume=pd.read_excel('data/会员消费报表.xlsx')
all_orders=pd.read_excel('data/全国销售订单数量表.xlsx')
custom_consume.head() 显示结果:

为会员消费报表添加年月列
#添加年月 这里年月要转换成整数,因为等会后面要链接的字段是整数
custom_consume.loc[:,'年月']=pd.to_datetime(custom_consume['订单日期']).apply(lambda x:datetime.strftime(x,'%Y%m')).astype(np.int)
custom_consume.head() 显示结果:

为会员消费报表添加地区编码
custom_consume=pd.merge(custom_consume,store_info[['店铺代码','地区编码']],on='店铺代码')
custom_consume.head() 显示结果:

剔除电商数据,统计会员购买订单数量
# margins参数 每行每列求和
member_orders=custom_consume[custom_consume['地区编码']!='GBL6D01'].pivot_table(values = '消费数量',index='地区编码',columns='年月',aggfunc=sum,margins=True)
member_orders 显示结果:

country_sales=all_orders.pivot_table(values = '全部订单数',index='地区代码',columns='年月',aggfunc=sum,margins=True)
country_sales 显示结果:

计算各地区会销比
result=member_orders/country_sales
result.applymap(lambda x: format(x,".2%")) 显示结果:

连带率的概念和为什么分析连带率
连带率是指销售的件数和交易的次数相除后的数值,反映的是顾客平均单次消费的产品件数
为什么分析连带率
连带率直接影响到客单价
连带率反应运营质量
连带率的计算
连带率 = 消费数量 / 订单数量
用到的数据:
会员消费报表.xlsx 会员消费记录
门店信息表.xlsx 建立门店地区对应关系
分析连带率的作用
通过连带率分析可以反映出人、货、场几个角度的业务问题
代码实现
统计订单的数量:需要对"订单号"去重,并且只要"下单"的数据,"退单"的不要
order_data=custom_consume.query(" 订单类型=='下单' & 地区编码!='GBL6D01'")
#去重 统计订单量需要去重 后面统计消费数量和消费金额不需要去重
order_count=order_data[['年月','地区编码','订单号']].drop_duplicates()
order_count=order_count.pivot_table(index = '地区编码',columns='年月',values='订单号',aggfunc='count') 显示结果:

统计消费商品数量
consume_count=order_data.pivot_table(values = '消费数量',index='地区编码',columns='年月',aggfunc=sum)
consume_count.head() 显示结果:

计算连带率
result=consume_count/order_count
#小数二位显示
result=result.applymap(lambda x:format(x,'.2f'))
result 显示结果:

复购率的概念和复购率分析的作用
复购率:指会员对该品牌产品或者服务的重复购买次数,重复购买率越多,则反应出会员对品牌的忠诚度就越高,反之则越低。
计算复购率需要指定时间范围
如何计算复购:会员消费次数一天之内只计算一次
复购率 = 一段时间内消费次数大于1次的人数 / 总消费人数
复购率分析的作用:通过复购率分析可以反映出运营状态
计算步骤
统计会员消费次数与是否复购
计算复购率并定义函数
统计2018年01月~2018年12月复购率和2018年02月~2019年01月复购率
计算复购率环比
代码实现
统计会员消费次数与是否复购
由于一个会员同一天消费多次也算一次消费,所以会员消费次数按一天一次计算 因此需要对"会员卡号"和"时间"进行去重
order_data=custom_consume.query("订单类型=='下单'")
#因为需要用到地区编号和年月 所以选择 订单日期 卡号 年月 地区编码 四个字段一起去重
order_data=order_data[['订单日期','卡号','年月','地区编码']].drop_duplicates()
consume_count = order_data.pivot_table(index =['地区编码','卡号'],values='订单日期',aggfunc='count').reset_index()
consume_count.rename(columns={'订单日期':'消费次数'},inplace=True)
consume_count 显示结果:

109171 rows × 3 columns
判断是否复购
consume_count['是否复购']=consume_count['消费次数']>1
consume_count 显示结果:

109171 rows × 4 columns
计算复购率并定义函数
统计每个地区的购买人数和复购人数
depart_data=consume_count.pivot_table(index = ['地区编码'],values=['消费次数','是否复购'],aggfunc={'消费次数':'count','是否复购':'sum'})
depart_data.columns=['复购人数','购买人数']
depart_data 显示结果:

计算复购率
depart_data.loc[:,'复购率']=depart_data['复购人数']/depart_data['购买人数']
depart_data 显示结果:

上面计算的数据为所有数据的复购率,我们要统计每年的复购率,所以要先对数据进行订单日期筛选,这里我们定义一个函数
def stats_reorder(start,end,col):
"""
统计指定起始年月的复购率
"""
#只要下单的数据 退单不统计
order_data=custom_consume.query("订单类型=='下单'")
#筛选日期
order_data= order_data[(order_data['年月']<=end) & (order_data['年月']>=start)]
#因为需要用到地区编号和年月 所以选择 订单日期 卡号 年月 地区编码 四个字段一起去重
order_data=order_data[['订单日期','卡号','年月','地区编码']].drop_duplicates()
#按照地区编码和卡号进行分组 统计订单日期数量 就是每个地区每个会员的购买次数
consume_count = order_data.pivot_table(index =['地区编码','卡号'],values='订单日期',aggfunc='count').reset_index()
#重命名列
consume_count.rename(columns={'订单日期':'消费次数'},inplace=True)
#判断是否复购
consume_count['是否复购']=consume_count['消费次数']>1
#统计每个地区的购买人数和复购人数
depart_data=consume_count.pivot_table(index = ['地区编码'],values=['消费次数','是否复购'],aggfunc={'消费次数':'count','是否复购':'sum'})
#重命名列
depart_data.columns=['复购人数','购买人数']
#计算复购率
depart_data[col+'复购率']=depart_data['复购人数']/depart_data['购买人数']
return depart_data 统计2018年01月~2018年12月复购率和2018年02月~2019年01月复购率
计算2018年的复购率
reorder_2018=stats_reorder(201801,201812,'2018.01-2018.12')
reorder_2018 显示结果:

计算2018年02月~2019年01月的复购率
reorder_2019=stats_reorder(201802,201901,'2018.02-2019.01')
reorder_2019 显示结果:

计算复购率环比
#合并数据
result=pd.concat([reorder_2018['2018.01-2018.12复购率'],reorder_2019['2018.02-2019.01复购率']],axis = 1)
#计算环比
result['环比']=(result['2018.02-2019.01复购率']-result['2018.01-2018.12复购率'])
#百分数显示
result=result.applymap(lambda x:format(x,'.2%'))
result 显示结果:

透视表是数据分析中经常使用的API,跟Excel中的数据透视表功能类似
Pandas的数据透视表,pivot_table,常用几个参数 index,values,columns,aggfuc,margin
Pandas的功能与groupby功能类似
视频教程学习地址:Pandas透视表(pivot_table)的使用方法