通过一个案例,快速掌握Pandas透视表(pivot_table)的使用方法!
ingemar-
2022年09月07日 16:03
收录于文集
共39篇

学习目标

  • 知道什么是透视表

  • 掌握Pandas透视表(pivot_table)的使用方法

视频教程学习地址:Pandas透视表(pivot_table)的使用方法​

1 Pandas 透视表概述

数据透视表(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的使用

2 零售会员数据分析案例

2.1 案例业务介绍

业务背景介绍

某女鞋连锁零售企业,当前业务以线下门店为主,线上销售为辅 通过对会员的注册数据以及的分析,监控会员运营情况,为后续会员运营提供决策依据 会员等级说明 ① 白银: 注册(0) ② 黄金: 下单(1~3888) ③ 铂金: 3888~6888 ④ 钻石: 6888以上

数据分析要达成的目标

描述性数据分析 使用业务数据,分析出会员运营的基本情况

案例中用到的数据

① 会员信息查询.xlsx ② 会员消费报表.xlsx  ③ 门店信息表.xlsx  ④ 全国销售订单数量表.xlsx

分析会员运营的基本情况

从量的角度分析会员运营情况: ① 整体会员运营情况(存量,增量)  ② 不同渠道(线上,线下)的会员运营情况  ③ 线下业务,拆解到不同的地区、门店会员运营情况 从质的角度分析会员运营情况: ① 会销比  ② 连带率  ③ 复购率

2.2 会员存量、增量分析

每月存量,增量是最基本的指标,通过会员数量考察会员运营情况

用到的数据:会员信息查询.xlsx

代码块
Python
自动换行
复制代码
import pandas as pd
custom_info=pd.read_excel('data/会员信息查询.xlsx')
custom_info.info()
复制成功

显示结果:

代码块
Shell
自动换行
复制代码
<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
复制成功

代码块
Python
自动换行
复制代码
#会员信息查询
custom_info.head()
复制成功

显示结果:

需要按月统计注册的会员数量,注册时间原始数据需要处理成年-月的形式

代码块
Python
自动换行
复制代码
# 给 会员信息表 添加年月列
from datetime import datetime
custom_info.loc[:,'注册年月'] = custom_info['注册时间'].apply(lambda x : x.strftime('%Y-%m'))
custom_info[['会员卡号','会员等级','会员来源','注册时间','注册年月']].head()
复制成功

显示结果:

代码块
Python
自动换行
复制代码
month_count = custom_info.groupby('注册年月')[['会员卡号']].count()
month_count.columns = ['月增量']
month_count.head()
复制成功

显示结果:

用数据透视表实现相同功能:dataframe.pivot_table()

  • index:行索引,传入原始数据的列名 原始数据的哪一个列作为新生成df中行索引

  • columns:列索引,传入原始数据的列名 原始数据的哪一个列作为新生成df中列名

  • values: 要做聚合操作的列名

  • aggfunc:聚合函数

代码块
Python
自动换行
复制代码
custom_info.pivot_table(index = '注册年月',values = '会员卡号',aggfunc = 'count')
复制成功

显示结果:

计算存量  cumsum  对某一列 做累积求和   1  1+2   1+2+3  1+2+3+4  ...

代码块
Python
自动换行
复制代码
#通过cumsum 对月增量做累积求和
month_count.loc[:,'存量'] = month_count['月增量'].cumsum()
month_count
复制成功

显示结果:

可视化,需要去除第一个月数据,第一个月数据是之前所有会员数量的累积(数据质量问题)

代码块
Python
自动换行
复制代码
#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)
复制成功

显示结果:

2.3 增量等级分布

会员增量存量不能真实反映会员运营的质量,需要对会员的增量存量数据做进一步拆解

从哪些维度来拆解?

  • 从指标构成来拆解:会员 = 白银会员+黄金会员+铂金会员+钻石会员

  • 从业务流程来拆解:当前案例,业务分线上、线下,又可以进一步拆解:按大区,按门店

会员等级分布分析的目的和要分析的指标

  • 会员按照等级拆解分为:

① 白银: 注册(0)  ② 黄金: 下单(1~3888)  ③ 铂金: 3888~6888  ④ 钻石: 6888以上

  • 由于会员等级跟消费金额挂钩,所以会员等级分布分析可以说明会员的质量

通过groupby实现,注册年月,会员等级,按这两个字段分组,对任意字段计数

代码块
Python
自动换行
复制代码
month_degree_count =custom_info.groupby(['注册年月','会员等级'])[['会员卡号']].count()
month_degree_count
复制成功

显示结果:

80 rows × 1 columns

分组之后得到的是multiIndex类型的索引,将multiIndex索引变成普通索引

代码块
Python
自动换行
复制代码
#使用reset_index()
month_degree_count.reset_index()
复制成功

显示结果:

80 rows × 3 columns

代码块
Python
自动换行
复制代码
#使用unstack()
month_degree_count.unstack()
复制成功

显示结果:

使用透视表实现

代码块
Python
自动换行
复制代码
member_rating = custom_info.pivot_table(index = '注册年月',columns='会员等级',values='会员卡号',aggfunc = 'count')
member_rating
复制成功

显示结果:

代码块
Python
自动换行
复制代码
#去掉首月数据
member_rating=member_rating[1:]
复制成功

pandas绘制图表

代码块
Python
自动换行
复制代码
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)
复制成功

显示结果:

2.4 增量等级占比分析

增量等级占比分析,查看增量会员的消费情况

代码块
Python
自动换行
复制代码
#按行求和
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
复制成功

显示结果:

绘图

代码块
Python
自动换行
复制代码
member_rating[['白银会员占比','黄金会员占比']].plot(color=['r','g'],ylabel='占比',figsize=(16,8),grid=True)
plt.title("会员等级占比分析",fontsize=20)
复制成功

显示结果:

2.5 整体等级分布

计算各个等级会员占整体的百分比

  • 思路:按照会员等级分组,计算每组的会员数量,用每组会员数量/全部会员数量

代码块
Python
自动换行
复制代码
#会员按等级分组groupby实现
ratio = custom_info.groupby('会员等级')[['会员卡号']].count()
#另一种写法
custom_info.groupby('会员等级').agg({'会员卡号':'count'})
#会员按等级分组透视表实现
ratio = custom_info.pivot_table(index = '会员等级',values = '会员卡号',aggfunc = 'count')
复制成功

显示结果:

代码块
Python
自动换行
复制代码
# 计算占比
ratio.columns=['会员数']
ratio.loc[:,'占比'] = ratio['会员数'].div(ratio['会员数'].sum())
ratio
复制成功

显示结果:

报表可视化

代码块
Python
自动换行
复制代码
# autopct 显示数据标签,并指定保留小数位数
ratio.loc[['白银会员','钻石会员','黄金会员','铂金会员'],'占比'].plot.pie(figsize=(16,8),autopct='%.1f%%',fontsize=16)
复制成功

显示结果:

2.6 线上线下增量分析

从业务角度,将会员数据拆分成线上和线下,比较每月线上线下会员的运营情况

将“会员来源”字段进行拆解,统计线上线下会员增量

代码块
Python
自动换行
复制代码
#按会员来源进行分组 使用groupby实现
from_data = custom_info.groupby(['注册年月','会员来源'])[['会员卡号']].count()
from_data = from_data.unstack()
from_data.columns = ['电商入口', '线下扫码']
from_data = from_data[1:]
from_data
复制成功

显示结果:

代码块
Python
自动换行
复制代码
# 透视表实现
custom_info.pivot_table(index = ['注册年月'],columns='会员来源',values ='会员卡号',aggfunc = 'count')
复制成功

可视化

代码块
Python
自动换行
复制代码
from_data.plot(figsize=(20,8),fontsize=16,grid=True)
plt.title("电商与线下会员增量分析",fontsize=18)
复制成功

显示结果:

2.7 地区店均会员数量

会员信息查询表中,只有店铺信息,没有地区信息,需要从门店信息表中关联地区信息

代码块
Python
自动换行
复制代码
#查看门店信息表
store_info = pd.read_excel('data/门店信息表.XLSX')
store_info
复制成功

显示结果:

只需要用到门店信息表中的[['店铺代码&#​39;,'地区编码&#​39;]] 两列

代码块
Python
自动换行
复制代码
store_info[['店铺代码','地区编码']].head()
复制成功

显示结果:

使用custom_info与store_info 关联,将地区编码添加到custom_info中

代码块
Python
自动换行
复制代码
custom_info1 = pd.merge(custom_info,store_info[['店铺代码','地区编码']],left_on='所属店铺编码',right_on='店铺代码')
复制成功

显示结果:

代码块
Python
自动换行
复制代码
#统计不同地区的会员数量 注意只统计线下,不统计电商渠道 GBL6D01为电商
district = custom_info1[custom_info1['地区编码']!='GBL6D01'].groupby('地区编码')[['会员卡号']].count()
#修改列名
district.columns = ['会员数量']
district
复制成功

显示结果:

代码块
Python
自动换行
复制代码
district['店铺数'] = custom_info1[['地区编码','所属店铺编码']].drop_duplicates().groupby('地区编码')['所属店铺编码'].count()
district
复制成功

显示结果:

代码块
Python
自动换行
复制代码
district.loc[:,'每店平均会员数']=round(district['会员数量'].div(district['店铺数']))
#计算总体平均数
district.loc[:,'总平均会员数']=district['会员数量'].sum()/district['店铺数'].sum()
#排序
district=district.sort_values(by='每店平均会员数',ascending=False)
district.head()
复制成功

显示结果:

数据可视化

代码块
Python
自动换行
复制代码
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)
复制成功

显示结果:

2.8 各地区会销比

会销比的计算和分析会销比的作用

  • 会销比 = 会员消费的金额 / 全部客户消费的金额

  • 由于数据脱敏的原因,没有全部客户消费金额的数据,所以用如下方式替换

  • 会销比 = 会员消费的订单数 / 全部销售订单数

  • 会销比统计的是会员消费占所有销售金额的比例

  • 通过会销比可以衡量会员的整体质量

加载数据

代码块
Python
自动换行
复制代码
custom_consume=pd.read_excel('data/会员消费报表.xlsx')
all_orders=pd.read_excel('data/全国销售订单数量表.xlsx')
custom_consume.head()
复制成功

显示结果:

为会员消费报表添加年月列

代码块
Python
自动换行
复制代码
#添加年月  这里年月要转换成整数,因为等会后面要链接的字段是整数
custom_consume.loc[:,'年月']=pd.to_datetime(custom_consume['订单日期']).apply(lambda x:datetime.strftime(x,'%Y%m')).astype(np.int)
custom_consume.head()
复制成功

显示结果:

为会员消费报表添加地区编码

代码块
Python
自动换行
复制代码
custom_consume=pd.merge(custom_consume,store_info[['店铺代码','地区编码']],on='店铺代码')
custom_consume.head()
复制成功

显示结果:

剔除电商数据,统计会员购买订单数量

代码块
Python
自动换行
复制代码
# margins参数 每行每列求和
member_orders=custom_consume[custom_consume['地区编码']!='GBL6D01'].pivot_table(values = '消费数量',index='地区编码',columns='年月',aggfunc=sum,margins=True)
member_orders
复制成功

显示结果:

代码块
Python
自动换行
复制代码
country_sales=all_orders.pivot_table(values = '全部订单数',index='地区代码',columns='年月',aggfunc=sum,margins=True)
country_sales
复制成功

显示结果:

计算各地区会销比

代码块
Python
自动换行
复制代码
result=member_orders/country_sales
result.applymap(lambda x: format(x,".2%"))
复制成功

显示结果:

2.9 会员连带率分析

连带率的概念和为什么分析连带率

  • 连带率是指销售的件数和交易的次数相除后的数值,反映的是顾客平均单次消费的产品件数

  • 为什么分析连带率

    • 连带率直接影响到客单价

    • 连带率反应运营质量

连带率的计算

  • 连带率 = 消费数量 / 订单数量

用到的数据:

  • 会员消费报表.xlsx       会员消费记录

  • 门店信息表.xlsx         建立门店地区对应关系

分析连带率的作用

  • 通过连带率分析可以反映出人、货、场几个角度的业务问题

代码实现

统计订单的数量:需要对"订单号&#​34;去重,并且只要"下单&#​34;的数据,"退单&#​34;的不要

代码块
Python
自动换行
复制代码
order_data=custom_consume.query(" 订单类型=='下单' & 地区编码!='GBL6D01'")
#去重  统计订单量需要去重  后面统计消费数量和消费金额不需要去重
order_count=order_data[['年月','地区编码','订单号']].drop_duplicates()
order_count=order_count.pivot_table(index = '地区编码',columns='年月',values='订单号',aggfunc='count')
复制成功

显示结果:

统计消费商品数量

代码块
Python
自动换行
复制代码
consume_count=order_data.pivot_table(values = '消费数量',index='地区编码',columns='年月',aggfunc=sum)
consume_count.head()
复制成功

显示结果:

计算连带率

代码块
Python
自动换行
复制代码
result=consume_count/order_count
#小数二位显示
result=result.applymap(lambda x:format(x,'.2f'))
result
复制成功

显示结果:

2.10 会员复购率分析

复购率的概念和复购率分析的作用

  • 复购率:指会员对该品牌产品或者服务的重复购买次数,重复购买率越多,则反应出会员对品牌的忠诚度就越高,反之则越低。

  • 计算复购率需要指定时间范围

  • 如何计算复购:会员消费次数一天之内只计算一次

  • 复购率 = 一段时间内消费次数大于1次的人数 / 总消费人数

  • 复购率分析的作用:通过复购率分析可以反映出运营状态

计算步骤

  • 统计会员消费次数与是否复购

  • 计算复购率并定义函数

  • 统计2018年01月~2018年12月复购率和2018年02月~2019年01月复购率

  • 计算复购率环比

代码实现

统计会员消费次数与是否复购

  • 由于一个会员同一天消费多次也算一次消费,所以会员消费次数按一天一次计算 因此需要对"会员卡号&#​34;和"时间&#​34;进行去重

代码块
Python
自动换行
复制代码
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

判断是否复购

代码块
Python
自动换行
复制代码
consume_count['是否复购']=consume_count['消费次数']>1
consume_count
复制成功

显示结果:

109171 rows × 4 columns

计算复购率并定义函数

  • 统计每个地区的购买人数和复购人数

代码块
Python
自动换行
复制代码
depart_data=consume_count.pivot_table(index = ['地区编码'],values=['消费次数','是否复购'],aggfunc={'消费次数':'count','是否复购':'sum'})
depart_data.columns=['复购人数','购买人数']
depart_data
复制成功

显示结果:

计算复购率

代码块
Python
自动换行
复制代码
depart_data.loc[:,'复购率']=depart_data['复购人数']/depart_data['购买人数']
depart_data
复制成功

显示结果:

上面计算的数据为所有数据的复购率,我们要统计每年的复购率,所以要先对数据进行订单日期筛选,这里我们定义一个函数

代码块
Python
自动换行
复制代码
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年的复购率

代码块
Python
自动换行
复制代码
reorder_2018=stats_reorder(201801,201812,'2018.01-2018.12')
reorder_2018
复制成功

显示结果:

  • 计算2018年02月~2019年01月的复购率

代码块
Python
自动换行
复制代码
reorder_2019=stats_reorder(201802,201901,'2018.02-2019.01')
reorder_2019
复制成功

显示结果:

  • 计算复购率环比

代码块
Python
自动换行
复制代码
#合并数据
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)的使用方法​