Python数据分析第8天 - 运营复盘项目实战¶

In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'].insert(0, 'SimHei')
plt.rcParams['axes.unicode_minus'] = False
In [2]:
%config InlineBackend.figure_format = 'svg'
In [9]:
# 加载订单明细表
orders = pd.read_csv(
    '../wenjian/orders.csv',
    true_values=['是'],
    false_values=['否'],
    # converters={'orderTime': pd.to_datetime}
)
orders.head(3)
Out[9]:
orderID userID goodsID num orderAmount payment orderTime chargeback
0 sys-2021-129388536 user-233240 PR000366 1 838 838 2021-01-05 00:01:11 False
1 sys-2021-129388537 user-184666 PR000716 4 3344 3344 2021-01-05 00:02:12 True
2 sys-2021-129388538 user-283751 PR000323 1 1648 1648 2021-01-05 00:02:46 True
In [10]:
orders.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 33501 entries, 0 to 33500
Data columns (total 8 columns):
 #   Column       Non-Null Count  Dtype 
---  ------       --------------  ----- 
 0   orderID      33501 non-null  object
 1   userID       33501 non-null  object
 2   goodsID      33501 non-null  object
 3   num          33501 non-null  int64 
 4   orderAmount  33501 non-null  int64 
 5   payment      33501 non-null  int64 
 6   orderTime    33501 non-null  object
 7   chargeback   33501 non-null  bool  
dtypes: bool(1), int64(3), object(4)
memory usage: 1.8+ MB
In [11]:
orders['orderTime'] = pd.to_datetime(orders.orderTime)
orders.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 33501 entries, 0 to 33500
Data columns (total 8 columns):
 #   Column       Non-Null Count  Dtype         
---  ------       --------------  -----         
 0   orderID      33501 non-null  object        
 1   userID       33501 non-null  object        
 2   goodsID      33501 non-null  object        
 3   num          33501 non-null  int64         
 4   orderAmount  33501 non-null  int64         
 5   payment      33501 non-null  int64         
 6   orderTime    33501 non-null  datetime64[ns]
 7   chargeback   33501 non-null  bool          
dtypes: bool(1), datetime64[ns](1), int64(3), object(3)
memory usage: 1.8+ MB
In [ ]:
orders.orderTime.agg(['min', 'max'])
In [12]:
def make_tag(day):
    if day < 8: return '预热期'
    elif day < 11: return '活动期'
    return '返场期'


# 运营活动分为三个阶段,分别是:预热期(5-7日)、活动期(8-10日)和返场期(11-13日)
orders['stage'] = orders.orderTime.dt.day.map(make_tag).astype('category').cat.reorder_categories(['预热期', '活动期', '返场期'])
orders.head(3)
Out[12]:
orderID userID goodsID num orderAmount payment orderTime chargeback stage
0 sys-2021-129388536 user-233240 PR000366 1 838 838 2021-01-05 00:01:11 False 预热期
1 sys-2021-129388537 user-184666 PR000716 4 3344 3344 2021-01-05 00:02:12 True 预热期
2 sys-2021-129388538 user-283751 PR000323 1 1648 1648 2021-01-05 00:02:46 True 预热期
In [13]:
# 订单是否参与了活动(有没有享受到活动优惠)
orders['inActivity'] = orders.payment < orders.orderAmount
orders.head(3)
Out[13]:
orderID userID goodsID num orderAmount payment orderTime chargeback stage inActivity
0 sys-2021-129388536 user-233240 PR000366 1 838 838 2021-01-05 00:01:11 False 预热期 False
1 sys-2021-129388537 user-184666 PR000716 4 3344 3344 2021-01-05 00:02:12 True 预热期 False
2 sys-2021-129388538 user-283751 PR000323 1 1648 1648 2021-01-05 00:02:46 True 预热期 False
In [14]:
# 加载商品表
products = pd.read_csv('../wenjian/products.csv')
products.head(3)
Out[14]:
goodsID price category cost key
0 PR000001 785 商品 299 False
1 PR000002 1310 家居 458 False
2 PR000003 2325 家居 837 True
In [15]:
# 处理异常值
products['category'] = products.category.replace('商品', '食品')
products.category.value_counts()
Out[15]:
category
美妆    490
食品    319
家居    191
Name: count, dtype: int64
In [ ]:
products.info()
In [16]:
# 加载用户表
users = pd.read_csv(
    '../wenjian/users.csv',
    usecols=['userID', 'age', 'sex', 'recentAcc', 'channelID', 'area', 'isOld'],
    converters={'recentAcc': pd.to_datetime}
)
users.head(3)
Out[16]:
userID age sex recentAcc channelID area isOld
0 user-550507 39 女 2021-01-12 渠道-52 山东 False
1 user-499937 30 男 2021-01-08 渠道-89 河南 True
2 user-515582 39 女 2021-01-09 渠道-89 四川 True
In [17]:
users.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 69395 entries, 0 to 69394
Data columns (total 7 columns):
 #   Column     Non-Null Count  Dtype         
---  ------     --------------  -----         
 0   userID     69395 non-null  object        
 1   age        69395 non-null  int64         
 2   sex        69395 non-null  object        
 3   recentAcc  69395 non-null  datetime64[ns]
 4   channelID  69395 non-null  object        
 5   area       69395 non-null  object        
 6   isOld      69395 non-null  bool          
dtypes: bool(1), datetime64[ns](1), int64(1), object(4)
memory usage: 3.2+ MB
In [18]:
# 清除掉非活动期间访问的用户
index = users[users.recentAcc.dt.day < 5].index
users.drop(index=index, inplace=True)
In [19]:
orders = pd.merge(orders, products, how='inner', on='goodsID')
orders
Out[19]:
orderID userID goodsID num orderAmount payment orderTime chargeback stage inActivity price category cost key
0 sys-2021-129388536 user-233240 PR000366 1 838 838 2021-01-05 00:01:11 False 预热期 False 838 食品 208 False
1 sys-2021-129388537 user-184666 PR000716 4 3344 3344 2021-01-05 00:02:12 True 预热期 False 836 家居 217 False
2 sys-2021-129388538 user-283751 PR000323 1 1648 1648 2021-01-05 00:02:46 True 预热期 False 1648 食品 531 False
3 sys-2021-129388539 user-279635 PR000652 1 651 651 2021-01-05 00:03:37 False 预热期 False 651 美妆 187 True
4 sys-2021-129388540 user-124652 PR000774 2 2830 2830 2021-01-05 00:04:44 False 预热期 False 1415 美妆 462 False
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
33496 sys-2021-129422913 user-235535 PR000164 4 2372 2372 2021-01-13 23:57:24 True 返场期 False 593 家居 180 False
33497 sys-2021-129422914 user-139042 PR000096 1 661 661 2021-01-13 23:57:51 False 返场期 False 661 美妆 185 False
33498 sys-2021-129422915 user-133379 PR000984 1 696 696 2021-01-13 23:58:19 False 返场期 False 696 家居 272 True
33499 sys-2021-129422916 user-156013 PR000753 4 5936 5936 2021-01-13 23:59:24 False 返场期 False 1484 美妆 451 False
33500 sys-2021-129422917 user-271551 PR000738 1 1014 1014 2021-01-13 23:59:45 False 返场期 False 1014 美妆 319 False

33501 rows × 14 columns

In [20]:
orders['profit'] = orders.payment - orders.cost * orders.num
orders
Out[20]:
orderID userID goodsID num orderAmount payment orderTime chargeback stage inActivity price category cost key profit
0 sys-2021-129388536 user-233240 PR000366 1 838 838 2021-01-05 00:01:11 False 预热期 False 838 食品 208 False 630
1 sys-2021-129388537 user-184666 PR000716 4 3344 3344 2021-01-05 00:02:12 True 预热期 False 836 家居 217 False 2476
2 sys-2021-129388538 user-283751 PR000323 1 1648 1648 2021-01-05 00:02:46 True 预热期 False 1648 食品 531 False 1117
3 sys-2021-129388539 user-279635 PR000652 1 651 651 2021-01-05 00:03:37 False 预热期 False 651 美妆 187 True 464
4 sys-2021-129388540 user-124652 PR000774 2 2830 2830 2021-01-05 00:04:44 False 预热期 False 1415 美妆 462 False 1906
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
33496 sys-2021-129422913 user-235535 PR000164 4 2372 2372 2021-01-13 23:57:24 True 返场期 False 593 家居 180 False 1652
33497 sys-2021-129422914 user-139042 PR000096 1 661 661 2021-01-13 23:57:51 False 返场期 False 661 美妆 185 False 476
33498 sys-2021-129422915 user-133379 PR000984 1 696 696 2021-01-13 23:58:19 False 返场期 False 696 家居 272 True 424
33499 sys-2021-129422916 user-156013 PR000753 4 5936 5936 2021-01-13 23:59:24 False 返场期 False 1484 美妆 451 False 4132
33500 sys-2021-129422917 user-271551 PR000738 1 1014 1014 2021-01-13 23:59:45 False 返场期 False 1014 美妆 319 False 695

33501 rows × 15 columns

In [21]:
# 按阶段统计各项指标
temp1 = pd.pivot_table(
    orders,
    index='stage',
    values=['orderAmount', 'orderID', 'num', 'userID'],
    aggfunc={
        'orderAmount': 'sum',
        'orderID': 'nunique',
        'num': 'sum',
        'userID': 'nunique'
    },
    observed=True
).rename(
    columns={'orderAmount': 'GMV', 'num': '商品数量', 'orderID': '订单数量', 'userID': '用户数量'},
)
temp1
Out[21]:
商品数量 GMV 订单数量 用户数量
stage
预热期 17155 18004237 6273 6059
活动期 40789 42794651 15441 14769
返场期 30331 31777545 11787 11312
In [22]:
temp2 = pd.pivot_table(
    orders.query('not chargeback'),
    index='stage',
    values=['payment', 'profit', 'orderID', 'num'],
    aggfunc={
        'payment': 'sum',
        'profit': 'sum',
        'num': 'sum',
        'orderID': 'nunique'
    },
    observed=True
).rename(
    columns={'payment': '净销售额', 'num': '成交商品数量', 'orderID': '成交订单数量', 'profit': '毛利润'},
)
temp2
Out[22]:
成交商品数量 成交订单数量 净销售额 毛利润
stage
预热期 14159 5164 14841296 10387440
活动期 26050 9841 25636091 17442507
返场期 24207 9392 24215453 16580731
In [23]:
pd.merge(temp1, temp2, left_index=True, right_index=True)
Out[23]:
商品数量 GMV 订单数量 用户数量 成交商品数量 成交订单数量 净销售额 毛利润
stage
预热期 17155 18004237 6273 6059 14159 5164 14841296 10387440
活动期 40789 42794651 15441 14769 26050 9841 25636091 17442507
返场期 30331 31777545 11787 11312 24207 9392 24215453 16580731
In [24]:
result1 = pd.concat((temp1, temp2), axis=1)
result1
Out[24]:
商品数量 GMV 订单数量 用户数量 成交商品数量 成交订单数量 净销售额 毛利润
stage
预热期 17155 18004237 6273 6059 14159 5164 14841296 10387440
活动期 40789 42794651 15441 14769 26050 9841 25636091 17442507
返场期 30331 31777545 11787 11312 24207 9392 24215453 16580731
In [25]:
result1['毛利率'] = result1.毛利润 / result1.净销售额
result1['AOV'] = (result1.净销售额 / result1.成交订单数量).round(2)
result1['连带率'] = (result1.成交商品数量 / result1.成交订单数量).round(2)
result1['客单价'] = (result1.净销售额 / result1.用户数量).round(2)
result1['拒退率'] = 1 - result1.成交订单数量 / result1.订单数量
result1
Out[25]:
商品数量 GMV 订单数量 用户数量 成交商品数量 成交订单数量 净销售额 毛利润 毛利率 AOV 连带率 客单价 拒退率
stage
预热期 17155 18004237 6273 6059 14159 5164 14841296 10387440 0.699901 2873.99 2.74 2449.46 0.176789
活动期 40789 42794651 15441 14769 26050 9841 25636091 17442507 0.680389 2605.03 2.65 1735.80 0.362671
返场期 30331 31777545 11787 11312 24207 9392 24215453 16580731 0.684717 2578.31 2.58 2140.69 0.203190
In [26]:
# 计算定基变化百分比
result2 = pd.concat((result1.pct_change(1)[:2], result1.pct_change(2)[2:3]))
result2.style.format(formatter='{:.2%}', na_rep='------')
Out[26]:
  商品数量 GMV 订单数量 用户数量 成交商品数量 成交订单数量 净销售额 毛利润 毛利率 AOV 连带率 客单价 拒退率
stage                          
预热期 ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------
活动期 137.77% 137.69% 146.15% 143.75% 83.98% 90.57% 72.73% 67.92% -2.79% -9.36% -3.28% -29.14% 105.14%
返场期 76.81% 76.50% 87.90% 86.70% 70.97% 81.87% 63.16% 59.62% -2.17% -10.29% -5.84% -12.61% 14.93%
In [27]:
# 绘制柱状图对比数据
result1.plot(
    figsize=(8, 4),
    kind='bar',
    y=['GMV', '净销售额'],
    width=0.4,
    xlabel='',
    color=['#1679AB', '#81A263']
)

plt.plot(np.arange(3) - 0.1, result1.GMV, marker='^', linewidth=0.8, color='#BC5A94', linestyle='--')
plt.plot(np.arange(3) + 0.1, result1.净销售额, marker='^', linewidth=0.8, color='#BC5A94', linestyle='--')

for i in range(1, 3):
    plt.text(i - 0.1, result1.GMV.iloc[i], f'{result2.GMV.iloc[i]:.2%}')
    plt.text(i + 0.1, result1.净销售额.iloc[i], f'{result2.净销售额.iloc[i]:.2%}')

plt.title('活动期间GMV和净销售额对比', fontdict={'size': 20, 'color': '#1A2130'})
plt.xticks(rotation=0)
plt.ylim(0, 50000000)
plt.ticklabel_format(axis='y', style='plain')
plt.show()
No description has been provided for this image
In [28]:
result3 = pd.pivot_table(
    orders.query('not chargeback'),
    index=['category'],
    values=['payment', 'profit', 'orderID', 'num', 'userID'],
    aggfunc={
        'payment': 'sum',
        'profit': 'sum',
        'num': 'sum',
        'orderID': 'nunique',
        'userID': 'nunique'
    },
    observed=True
).rename(
    columns={'num': '成交商品数量', 'orderID': '成交订单数量', 'payment': '净销售额', 'profit': '毛利润', 'userID': '成交用户数量'}
)
result3['毛利率'] = result3.毛利润 / result3.净销售额
result3['AOV'] = (result3.净销售额 / result3.成交订单数量).round(2)
result3['连带率'] = (result3.成交商品数量 / result3.成交订单数量).round(2)
result3['客单价'] = (result3.净销售额 / result3.成交用户数量).round(2)
result3
Out[28]:
成交商品数量 成交订单数量 净销售额 毛利润 成交用户数量 毛利率 AOV 连带率 客单价
category
家居 12188 4608 11768215 8117181 4557 0.689755 2553.87 2.64 2582.45
美妆 31666 12041 32087809 21934662 11738 0.683582 2664.88 2.63 2733.67
食品 20562 7748 20836816 14358835 7621 0.689109 2689.32 2.65 2734.13
In [29]:
result4 = pd.pivot_table(
    orders.query('not chargeback'),
    index=['stage', 'category'],
    values=['payment', 'profit', 'orderID', 'num', 'userID'],
    aggfunc={
        'payment': 'sum',
        'profit': 'sum',
        'num': 'sum',
        'orderID': 'nunique',
        'userID': 'nunique'
    },
    observed=True
).rename(
    columns={'num': '成交商品数量', 'orderID': '成交订单数量', 'payment': '净销售额', 'profit': '毛利润', 'userID': '成交用户数量'}
)
result4['毛利率'] = result4.毛利润 / result4.净销售额
result4['AOV'] = (result4.净销售额 / result4.成交订单数量).round(2)
result4['连带率'] = (result4.成交商品数量 / result4.成交订单数量).round(2)
result4['客单价'] = (result4.净销售额 / result4.成交用户数量).round(2)
result4
Out[29]:
成交商品数量 成交订单数量 净销售额 毛利润 成交用户数量 毛利率 AOV 连带率 客单价
stage category
预热期 家居 2784 993 2823369 1984482 989 0.702877 2843.27 2.80 2854.77
美妆 6914 2535 7293513 5087927 2500 0.697596 2877.13 2.73 2917.41
食品 4461 1636 4724414 3315031 1619 0.701681 2887.78 2.73 2918.11
活动期 家居 4806 1857 4477521 3056715 1851 0.682680 2411.16 2.59 2418.97
美妆 12866 4836 12852941 8716111 4769 0.678141 2657.76 2.66 2695.10
食品 8378 3148 8305629 5669681 3122 0.682631 2638.38 2.66 2660.36
返场期 家居 4598 1758 4467325 3075984 1742 0.688552 2541.14 2.62 2564.48
美妆 11886 4670 11941355 8130624 4597 0.680880 2557.04 2.55 2597.64
食品 7723 2964 7806773 5374123 2940 0.688392 2633.86 2.61 2655.36
In [30]:
temp3 = pd.pivot_table(
    orders.query('not chargeback'),
    index='userID',
    values=['payment', 'profit', 'num', 'orderID'],
    aggfunc={
        'payment': 'sum',
        'profit': 'sum',
        'num': 'sum',
        'orderID': 'nunique'
    }
)
temp3['buy'] = 1
temp3
Out[30]:
num orderID payment profit buy
userID
user-100000 1 1 1195 905 1
user-100032 4 2 5074 3156 1
user-100033 3 1 2154 1602 1
user-100034 1 1 1048 664 1
user-100038 4 1 2616 1964 1
... ... ... ... ... ...
user-548272 1 1 978 688 1
user-548274 7 1 9919 6370 1
user-548279 2 1 1848 1262 1
user-548280 4 1 4108 3092 1
user-548282 3 1 2685 1806 1

23119 rows × 5 columns

In [31]:
temp4 = pd.merge(users, temp3, how='left', on='userID').fillna(0)
temp4
Out[31]:
userID age sex recentAcc channelID area isOld num orderID payment profit buy
0 user-550507 39 女 2021-01-12 渠道-52 山东 False 0.0 0.0 0.0 0.0 0.0
1 user-499937 30 男 2021-01-08 渠道-89 河南 True 0.0 0.0 0.0 0.0 0.0
2 user-515582 39 女 2021-01-09 渠道-89 四川 True 0.0 0.0 0.0 0.0 0.0
3 user-519645 34 男 2021-01-10 渠道-00 广东 True 0.0 0.0 0.0 0.0 0.0
4 user-529356 24 女 2021-01-08 渠道-19 四川 False 0.0 0.0 0.0 0.0 0.0
... ... ... ... ... ... ... ... ... ... ... ... ...
66153 user-531290 24 女 2021-01-08 渠道-52 北京 False 0.0 0.0 0.0 0.0 0.0
66154 user-537409 33 女 2021-01-10 渠道-39 上海 False 0.0 0.0 0.0 0.0 0.0
66155 user-511000 40 女 2021-01-09 渠道-98 湖北 False 0.0 0.0 0.0 0.0 0.0
66156 user-518649 36 女 2021-01-10 渠道-00 上海 True 0.0 0.0 0.0 0.0 0.0
66157 user-545810 18 女 2021-01-10 渠道-39 上海 True 0.0 0.0 0.0 0.0 0.0

66158 rows × 12 columns

In [32]:
# 统计每个渠道的净销售额、毛利润、销售数量、订单数量、拉新用户数量、购买用户数量
result5 = pd.pivot_table(
    temp4,
    index='channelID',
    values=['payment', 'profit', 'num', 'orderID', 'userID', 'buy'],
    aggfunc={
        'payment': 'sum',
        'profit': 'sum',
        'num': 'sum',
        'orderID': 'sum',
        'userID': 'count',
        'buy': 'sum',
    }
).rename(
    columns={'payment': '净销售额', 'profit': '毛利润', 'num': '销售数量', 'orderID': '订单数量', 'userID': '拉新用户数', 'buy': '购买用户数'}
).astype('i8')
result5.sort_values(by='拉新用户数', ascending=False)
Out[32]:
购买用户数 销售数量 订单数量 净销售额 毛利润 拉新用户数
channelID
渠道-89 1005 2843 1059 2806740 1906726 11331
渠道-52 767 2120 814 2089450 1426467 8434
渠道-53 731 1972 764 1990945 1361766 7909
渠道-76 594 1668 633 1655802 1128539 6213
渠道-39 501 1438 530 1386851 946564 5663
渠道-00 466 1348 491 1344906 918124 5360
渠道-98 396 1081 420 1056999 726693 4272
渠道-28 389 1065 410 1072763 736434 4090
渠道-56 274 784 307 822426 558868 2841
渠道-16 232 608 241 601559 411468 2826
渠道-46 248 659 260 643569 440691 2805
渠道-78 206 552 215 547785 375983 2246
渠道-19 186 550 202 554238 378912 2168
In [33]:
# 统计不同渠道的转化率和客单价
result5['转化率'] = (result5.购买用户数 / result5.拉新用户数).round(4)
result5['ARPU'] = (result5.净销售额 / result5.拉新用户数).round(2)
result5['ARPPU'] = (result5.净销售额 / result5.购买用户数).round(2)
result5.sort_values(
    by='净销售额',
    ascending=False
).style.format(formatter={
    '转化率': '{:.2%}', 
    'ARPU': '{:,.2f}', 
    'ARPPU': '{:,.2f}'
})
Out[33]:
  购买用户数 销售数量 订单数量 净销售额 毛利润 拉新用户数 转化率 ARPU ARPPU
channelID                  
渠道-89 1005 2843 1059 2806740 1906726 11331 8.87% 247.70 2,792.78
渠道-52 767 2120 814 2089450 1426467 8434 9.09% 247.74 2,724.19
渠道-53 731 1972 764 1990945 1361766 7909 9.24% 251.73 2,723.59
渠道-76 594 1668 633 1655802 1128539 6213 9.56% 266.51 2,787.55
渠道-39 501 1438 530 1386851 946564 5663 8.85% 244.90 2,768.17
渠道-00 466 1348 491 1344906 918124 5360 8.69% 250.92 2,886.06
渠道-28 389 1065 410 1072763 736434 4090 9.51% 262.29 2,757.75
渠道-98 396 1081 420 1056999 726693 4272 9.27% 247.42 2,669.19
渠道-56 274 784 307 822426 558868 2841 9.64% 289.48 3,001.55
渠道-46 248 659 260 643569 440691 2805 8.84% 229.44 2,595.04
渠道-16 232 608 241 601559 411468 2826 8.21% 212.87 2,592.93
渠道-19 186 550 202 554238 378912 2168 8.58% 255.64 2,979.77
渠道-78 206 552 215 547785 375983 2246 9.17% 243.89 2,659.15
In [35]:
mean_users = result5.拉新用户数.mean()
mean_crate = result5.转化率.mean()
In [36]:
# 绘制渠道象限分析的散点图
plt.scatter(result5.拉新用户数, result5.转化率)
plt.plot([0, 12000], [mean_crate] * 2, color='r', linestyle='--', linewidth=0.5)
plt.plot([mean_users] * 2, [0.08, 0.1], color='r', linestyle='--', linewidth=0.5)
plt.xlim(0, 12000)
plt.ylim(0.08, 0.1)
for idx in result5.index:
    y, x = result5.at[idx, '转化率'], result5.at[idx, '拉新用户数']
    plt.text(x, y, idx, ha='center', va='bottom')
plt.show()
No description has been provided for this image
In [37]:
# 统计不同性别的净销售额、销售数量、订单数量、拉新用户数量、购买用户数量
result6 = pd.pivot_table(
    temp4,
    index='sex',
    values=['payment', 'num', 'orderID', 'userID', 'buy'],
    aggfunc={
        'payment': 'sum',
        'num': 'sum',
        'orderID': 'sum',
        'userID': 'count',
        'buy': 'sum',
    }
).astype('i8').rename(
    columns={'payment': '净销售额', 'num': '销售数量', 'orderID': '订单数量', 'userID': '拉新用户数', 'buy': '购买用户数'}
)
result6.index.name = '性别'
result6
Out[37]:
购买用户数 销售数量 订单数量 净销售额 拉新用户数
性别
女 3989 11209 4234 11106698 44398
男 2006 5479 2112 5467335 21760
In [38]:
# 统计不同性别的转化率和客单价
result6['转化率'] = result6.购买用户数 / result6.拉新用户数
result6['ARPU'] = result6.净销售额 / result6.拉新用户数
result6['ARPPU'] = result6.净销售额 / result6.购买用户数
result6.drop(
    columns=['拉新用户数', '购买用户数']
).style.format(formatter={
    '净销售额': '{:,}',
    '转化率': '{:.2%}', 
    'ARPU': '{:,.2f}', 
    'ARPPU': '{:,.2f}'
})
Out[38]:
  销售数量 订单数量 净销售额 转化率 ARPU ARPPU
性别            
女 11209 4234 11,106,698 8.98% 250.16 2,784.33
男 5479 2112 5,467,335 9.22% 251.26 2,725.49
In [39]:
temp4['ageGroup'] = pd.cut(
    temp4.age,
    bins=[18, 25, 35, 45, 55, 66],
    right=False,
    labels=['18-24岁', '25-34岁', '35-44岁', '45-54岁', '55岁+']
)
temp4
Out[39]:
userID age sex recentAcc channelID area isOld num orderID payment profit buy ageGroup
0 user-550507 39 女 2021-01-12 渠道-52 山东 False 0.0 0.0 0.0 0.0 0.0 35-44岁
1 user-499937 30 男 2021-01-08 渠道-89 河南 True 0.0 0.0 0.0 0.0 0.0 25-34岁
2 user-515582 39 女 2021-01-09 渠道-89 四川 True 0.0 0.0 0.0 0.0 0.0 35-44岁
3 user-519645 34 男 2021-01-10 渠道-00 广东 True 0.0 0.0 0.0 0.0 0.0 25-34岁
4 user-529356 24 女 2021-01-08 渠道-19 四川 False 0.0 0.0 0.0 0.0 0.0 18-24岁
... ... ... ... ... ... ... ... ... ... ... ... ... ...
66153 user-531290 24 女 2021-01-08 渠道-52 北京 False 0.0 0.0 0.0 0.0 0.0 18-24岁
66154 user-537409 33 女 2021-01-10 渠道-39 上海 False 0.0 0.0 0.0 0.0 0.0 25-34岁
66155 user-511000 40 女 2021-01-09 渠道-98 湖北 False 0.0 0.0 0.0 0.0 0.0 35-44岁
66156 user-518649 36 女 2021-01-10 渠道-00 上海 True 0.0 0.0 0.0 0.0 0.0 35-44岁
66157 user-545810 18 女 2021-01-10 渠道-39 上海 True 0.0 0.0 0.0 0.0 0.0 18-24岁

66158 rows × 13 columns

In [40]:
# 统计不同年龄段的净销售额、销售数量、订单数量、拉新用户数量、购买用户数量
result7 = pd.pivot_table(
    temp4,
    index='ageGroup',
    values=['payment', 'num', 'orderID', 'userID', 'buy'],
    aggfunc={
        'payment': 'sum',
        'num': 'sum',
        'orderID': 'sum',
        'userID': 'count',
        'buy': 'sum',
    },
    observed=True
).astype('i8').rename(
    columns={'payment': '净销售额', 'num': '销售数量', 'orderID': '订单数量', 'userID': '拉新用户数', 'buy': '购买用户数'}
)
result7
Out[40]:
购买用户数 销售数量 订单数量 净销售额 拉新用户数
ageGroup
18-24岁 1170 3244 1238 3231708 12261
25-34岁 1568 4410 1661 4371373 17338
35-44岁 1602 4519 1688 4443134 17380
45-54岁 1266 3411 1341 3447739 13711
55岁+ 389 1104 418 1080079 5468
In [41]:
# 统计不同年龄段的转化率和客单价
result7['转化率'] = result7.购买用户数 / result7.拉新用户数
result7['ARPU'] = result7.净销售额 / result7.拉新用户数
result7['ARPPU'] = result7.净销售额 / result7.购买用户数
result7.sort_values(
    by='净销售额',
    ascending=False
).style.format(formatter={
    '净销售额': '{:,}',
    '转化率': '{:.2%}', 
    'ARPU': '{:,.2f}', 
    'ARPPU': '{:,.2f}'
})
Out[41]:
  购买用户数 销售数量 订单数量 净销售额 拉新用户数 转化率 ARPU ARPPU
ageGroup                
35-44岁 1602 4519 1688 4,443,134 17380 9.22% 255.65 2,773.49
25-34岁 1568 4410 1661 4,371,373 17338 9.04% 252.13 2,787.87
45-54岁 1266 3411 1341 3,447,739 13711 9.23% 251.46 2,723.33
18-24岁 1170 3244 1238 3,231,708 12261 9.54% 263.58 2,762.14
55岁+ 389 1104 418 1,080,079 5468 7.11% 197.53 2,776.55
In [42]:
# 统计各省份的净销售额、销售数量、订单数量、拉新用户数量、购买用户数量
result8 = pd.pivot_table(
    temp4,
    index='area',
    values=['payment', 'profit', 'num', 'orderID', 'userID', 'buy'],
    aggfunc={
        'payment': 'sum',
        'profit': 'sum',
        'num': 'sum',
        'orderID': 'sum',
        'userID': 'count',
        'buy': 'sum',
    },
    observed=True
).astype('i8').rename(
    columns={'payment': '净销售额', 'profit': '毛利润', 'num': '销售数量', 'orderID': '订单数量', 'userID': '拉新用户数', 'buy': '购买用户数'}
)
result8
Out[42]:
购买用户数 销售数量 订单数量 净销售额 毛利润 拉新用户数
area
上海 721 2014 756 1951379 1325965 7889
云南 68 160 71 155529 105775 664
北京 728 2030 769 1981054 1360129 7949
四川 657 1881 699 1793699 1217002 7294
安徽 48 124 51 120022 85302 680
山东 537 1505 564 1544444 1057210 5967
山西 64 169 66 168417 115786 679
广东 648 1732 689 1714908 1174084 7302
广西 56 178 61 183028 124292 612
江苏 624 1736 656 1740676 1189495 7354
江西 71 191 76 192670 131827 677
河北 55 156 58 153676 101156 648
河南 61 157 63 145070 99357 646
浙江 431 1220 457 1245445 857575 4667
湖北 190 526 203 546404 370781 1962
湖南 256 722 272 724999 488082 2591
福建 478 1327 506 1352620 928288 5283
贵州 58 160 63 166793 112253 664
重庆 244 700 266 693200 472876 2630
In [43]:
# 统计各省份的转化率和客单价
result8['转化率'] = result8.购买用户数 / result8.拉新用户数
result8['ARPU'] = result8.净销售额 / result8.拉新用户数
result8['ARPPU'] = result8.净销售额 / result8.购买用户数
result8.sort_values(
    by='净销售额',
    ascending=False
).style.format(formatter={
    '净销售额': '{:,}',
    '转化率': '{:.2%}', 
    'ARPU': '{:,.2f}', 
    'ARPPU': '{:,.2f}'
})
Out[43]:
  购买用户数 销售数量 订单数量 净销售额 毛利润 拉新用户数 转化率 ARPU ARPPU
area                  
北京 728 2030 769 1,981,054 1360129 7949 9.16% 249.22 2,721.23
上海 721 2014 756 1,951,379 1325965 7889 9.14% 247.35 2,706.49
四川 657 1881 699 1,793,699 1217002 7294 9.01% 245.91 2,730.14
江苏 624 1736 656 1,740,676 1189495 7354 8.49% 236.70 2,789.54
广东 648 1732 689 1,714,908 1174084 7302 8.87% 234.85 2,646.46
山东 537 1505 564 1,544,444 1057210 5967 9.00% 258.83 2,876.06
福建 478 1327 506 1,352,620 928288 5283 9.05% 256.03 2,829.75
浙江 431 1220 457 1,245,445 857575 4667 9.24% 266.86 2,889.66
湖南 256 722 272 724,999 488082 2591 9.88% 279.81 2,832.03
重庆 244 700 266 693,200 472876 2630 9.28% 263.57 2,840.98
湖北 190 526 203 546,404 370781 1962 9.68% 278.49 2,875.81
江西 71 191 76 192,670 131827 677 10.49% 284.59 2,713.66
广西 56 178 61 183,028 124292 612 9.15% 299.07 3,268.36
山西 64 169 66 168,417 115786 679 9.43% 248.04 2,631.52
贵州 58 160 63 166,793 112253 664 8.73% 251.19 2,875.74
云南 68 160 71 155,529 105775 664 10.24% 234.23 2,287.19
河北 55 156 58 153,676 101156 648 8.49% 237.15 2,794.11
河南 61 157 63 145,070 99357 646 9.44% 224.57 2,378.20
安徽 48 124 51 120,022 85302 680 7.06% 176.50 2,500.46
In [44]:
# 统计新老用户的净销售额、销售数量、订单数量、拉新用户数量、购买用户数量
result9 = pd.pivot_table(
    temp4,
    index='isOld',
    values=['payment', 'profit', 'num', 'orderID', 'userID', 'buy'],
    aggfunc={
        'payment': 'sum',
        'profit': 'sum',
        'num': 'sum',
        'orderID': 'sum',
        'userID': 'count',
        'buy': 'sum',
    },
    observed=True
).astype('i8').rename(
    columns={'payment': '净销售额', 'profit': '毛利润', 'num': '销售数量', 'orderID': '订单数量', 'userID': '拉新用户数', 'buy': '购买用户数'}
).rename(
    index={False: '新用户', True: '老用户'}
)
result9
Out[44]:
购买用户数 销售数量 订单数量 净销售额 毛利润 拉新用户数
isOld
新用户 2292 6401 2428 6304970 4302207 25095
老用户 3703 10287 3918 10269063 7015028 41063
In [45]:
# 统计新老用户的转化率和客单价
result9['转化率'] = result9.购买用户数 / result9.拉新用户数
result9['ARPU'] = result9.净销售额 / result9.拉新用户数
result9['ARPPU'] = result9.净销售额 / result9.购买用户数
result9.sort_values(
    by='净销售额',
    ascending=False
).style.format(formatter={
    '净销售额': '{:,}',
    '转化率': '{:.2%}', 
    'ARPU': '{:,.2f}', 
    'ARPPU': '{:,.2f}'
})
Out[45]:
  购买用户数 销售数量 订单数量 净销售额 毛利润 拉新用户数 转化率 ARPU ARPPU
isOld                  
老用户 3703 10287 3918 10,269,063 7015028 41063 9.02% 250.08 2,773.17
新用户 2292 6401 2428 6,304,970 4302207 25095 9.13% 251.24 2,750.86
In [ ]:
# Todo: 建议进行用户相关维度、商品相关维度的交叉组合分析