当前位置:   article > 正文

Python库Pandas订单数据清洗,分析实战案例1-涉及RFM模型-超详细_python 数据分析 rfm

python 数据分析 rfm

订单数据分析和RFM模型

本文主要使用jupyter lab 进行数据分析

导入库和读取数据

导入需要用到的库
  1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. plt.rcParams['font.sans-serif'].insert(0, 'SimHei') # 设置中文字体
  5. plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
'
运行
读取数据
  1. orders_df = pd.read_excel('data/某电商平台2021年订单数据.xlsx', index_col='id')
  2. orders_df.info()

数据清洗

使用的相关方法

修改列的字段名

df.rename(columns={' ' : ' ', ' ' : ' ' })

 就地修改

inplace=True # 函数将会就地修改对象,而不返回新的对象。这意味着对原始对象的更改会直接生效,而不需要为新对象分配额外的内存空间。'
运行

 删除对应的行和列

  1. # 删除列
  2. df.drop('A', axis=1, inplace=True) # 在原始 DataFrame 中删除列 'A'
  3. # 删除行
  4. df.drop(0, axis=0, inplace=True) # 在原始 DataFrame 中删除第一行

根据条件在 Series 中对值进行过滤

  1. # 使用 where 函数进行过滤
  2. filtered_s = s.where(s > 3, 0) # 如果值大于3,保留原值,否则用0替换
  3. # 使用 mask 函数进行过滤
  4. masked_s = s.mask(s > 3, -1) # 如果值大于3,用-1替换,否则保留原值
 全部代码如下
  1. # 修改渠道字段的列名为channelID,平台字段的列名为platformType
  2. orders_df.rename(columns={'chanelID': 'channelID', 'platfromType': 'platformType'}, inplace=True)
  3. # 筛选出2021年的订单(orderTime在2021年)
  4. index = orders_df[orders_df.orderTime.dt.year != 2021].index
  5. orders_df.drop(index=index, inplace=True)
  6. # 删除支付金额(payment)小于0的订单,删除支付时间(payTime)早于下单时间(orderTime)的订单
  7. index = orders_df[(orders_df.payment < 0) | (orders_df.payTime < orders_df.orderTime)].index
  8. orders_df.drop(index=index, inplace=True)
  9. # 删除支付时长超过30分钟的订单
  10. index = orders_df[(orders_df.payTime - orders_df.orderTime).dt.total_seconds() > 1800].index
  11. orders_df.drop(index=index, inplace=True)
  12. # 对于支付金额(payment)大于订单金额(orderAmount)的订单,将支付金额修改为订单金额乘以平均折扣率
  13. a, b = orders_df[orders_df.payment <= orders_df.orderAmount][['orderAmount', 'payment']].sum()
  14. mean_discount = b / a
  15. # Series.where - 满足条件保留原来的值,不满足条件用第二个参数替换掉
  16. # Series.mask - 满足条件的被替换掉,不满足条件的保留原来的值
  17. orders_df['payment'] = orders_df.payment.where(
  18. orders_df.payment <= orders_df.orderAmount,
  19. (orders_df.orderAmount * mean_discount).round(2)
  20. )
  21. # 将渠道(channelID)字段的空值填充为众数
  22. most_common_channel = orders_df.channelID.mode()[0]
  23. orders_df.channelID.fillna(most_common_channel, inplace=True)
  24. orders_df.info()
  25. # 处理掉平台(platformType)字段的异常值(最后只有四种值:微信、支付宝、App、Web)
  26. orders_df['platformType'] = orders_df.platformType.str.replace(
  27. r'[\s·]', '', regex=True
  28. ).str.title(
  29. ).str.replace(
  30. r'薇信|Vx', '微信', regex=True
  31. ).str.replace(
  32. r'网页|网站', 'Web', regex=True
  33. )
  34. orders_df.platformType.unique()

数据分析

  1. # 统计出核心指标,包括:GMV、净销售额、客单价、拒退率、复购率
  2. gmv = orders_df.orderAmount.sum()
  3. sales = orders_df.query('not chargeback').payment.sum()
  4. arppu = sales / orders_df.userID.nunique()
  5. brate = orders_df.query('chargeback').orderID.count() / orders_df.orderID.count()
 计算复购率
  1. temp = pd.pivot_table(
  2. orders_df.query('not chargeback'),
  3. index='userID',
  4. values='orderID',
  5. aggfunc='nunique'
  6. ).rename(columns={'orderID': 'orderCount'})
  7. ser = temp.orderCount.map(lambda x: 1 if x > 1 else 0)
  8. rrate = ser.sum() / ser.count()
统计月度GMV和净销售额
  1. # 统计月度GMV和净销售额
  2. orders_df['month'] = orders_df.orderTime.dt.month
  3. temp1 = pd.pivot_table(
  4. orders_df,
  5. index='month',
  6. values='orderAmount',
  7. aggfunc='sum'
  8. ).round(2).rename(columns={'orderAmount': 'GMV'})
  9. temp2 = pd.pivot_table(
  10. orders_df.query('not chargeback'),
  11. index='month',
  12. values='payment',
  13. aggfunc='sum'
  14. ).round(2).rename(columns={'payment': '净销售额'})
  15. # pd.merge(temp1, temp2, how='inner', left_index=True, right_index=True)
  16. temp = pd.concat((temp1, temp2), axis=1)
  17. temp

  绘制折线图 - 月度GMV和净销售额 - plt
  1. temp.plot(kind='line', figsize=(10, 4), xlabel='', linewidth=0.5, linestyle='--', marker='^')
  2. plt.ylim(0, 14000000)
  3. plt.xticks(temp.index)
  4. plt.legend(loc='lower right')
  5. plt.show()

 指定 PyEcharts 在 Jupyter Lab 环境中正确显示图表

  1. from pyecharts.globals import CurrentConfig, NotebookType
  2. CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_LAB

 准备对应的数据

  1. months = [f'{x}月' for x in temp.index.values.tolist()]
  2. gmv = (temp.GMV / 1000000).round(2).tolist()
  3. sales = (temp.净销售额 / 1000000).round(2).tolist()
 绘制折线图 - 月度GMV和净销售额 - pyecharts
  1. import pyecharts.options as opts
  2. from pyecharts.charts import Line
  3. line_chart = Line(init_opts=opts.InitOpts(width='1000px', height='500px'))
  4. line_chart.add_xaxis(months)
  5. line_chart.add_yaxis("GMV", gmv)
  6. line_chart.add_yaxis(
  7. "净销售额",
  8. sales,
  9. markline_opts=opts.MarkLineOpts(
  10. data=[
  11. opts.MarkLineItem(type_="average"),
  12. ]
  13. )
  14. )
  15. line_chart.load_javascript()
line_chart.render_notebook()

 绘制饼图 - 各销售渠道的销售量占比
  1. ser = orders_df.query('not chargeback').groupby('channelID')['payment'].sum()
  2. ser

  1. import pyecharts.options as opts
  2. from pyecharts.charts import Pie
  3. x_data = ser.index.values.tolist()
  4. y_data = ser.values.tolist()
  5. data = [z for z in zip(x_data, y_data)]
  6. pie_chart = Pie()
  7. pie_chart.add(
  8. series_name="",
  9. data_pair=data,
  10. radius=["50%", "70%"],
  11. )
  12. pie_chart.set_global_opts(
  13. legend_opts=opts.LegendOpts(is_show=False)
  14. )
  15. pie_chart.set_series_opts(
  16. tooltip_opts=opts.TooltipOpts(
  17. trigger="item",
  18. formatter="{b}: {c}"
  19. ),
  20. label_opts=opts.LabelOpts(formatter="{b}: {d}%")
  21. )
  22. pie_chart.load_javascript()
pie_chart.render_notebook()
 
绘制条形图 - 星期几用户下单量
  1. # 统计星期几用户下单量最高
  2. orders_df['weekday'] = (orders_df.orderTime.dt.weekday + 1) % 7
  3. temp = orders_df.pivot_table(
  4. index='weekday',
  5. values='orderID',
  6. aggfunc='nunique'
  7. )
  8. temp.plot(kind='bar', figsize=(8, 4), xlabel='', legend=False)
  9. for i in np.arange(7):
  10. plt.text(i, temp.orderID[i] + 100, temp.orderID[i], ha='center', fontdict=dict(size=9))
  11. plt.xticks(np.arange(7), labels=[f'星期{x}' for x in '日一二三四五六'], rotation=0)
  12. plt.show()

绘制条形图 - 统计每个的各时段下单量
  1. # 统计每天哪个时段用户下单量最高
  2. orders_df['time'] = orders_df.orderTime.dt.floor('30T').dt.strftime('%H:%M')
  3. temp = pd.pivot_table(
  4. orders_df,
  5. index='time',
  6. values='orderID',
  7. aggfunc='nunique'
  8. )
  9. plt.figure(figsize=(10, 4), dpi=200)
  10. plt.bar(temp.index, temp.orderID, color=np.random.random((8, 3)), width=0.8)
  11. plt.xticks(rotation=75)
  12. plt.show()

 计算每个月复购率
  1. # 以自然月为窗口计算每个月的复购率
  2. temp = pd.pivot_table(
  3. orders_df.query('not chargeback'),
  4. index='userID',
  5. columns='month',
  6. values='orderID',
  7. aggfunc='nunique'
  8. )
  9. temp = temp.map(lambda x: x if np.isnan(x) else (1 if x > 1 else 0))
  10. temp.sum() / temp.count()

 

RFM模型 - 绘制饼图
  1. from datetime import datetime
  2. # 用RFM模型实现用户价值分群
  3. rfm_model_df = pd.pivot_table(
  4. orders_df.query('not chargeback'),
  5. index='userID',
  6. values=['orderTime', 'orderID', 'payment'],
  7. aggfunc={
  8. 'orderTime': 'max',
  9. 'orderID': 'nunique',
  10. 'payment': 'sum'
  11. }
  12. ).rename(columns={'orderTime': 'R', 'orderID': 'F', 'payment': 'M'})
  13. rfm_model_df['R'] = (datetime(2021, 12, 31, 23, 59, 59) - rfm_model_df.R).dt.days
  14. # reindex - 调整行索引或列索引的顺序(也可以用花式索引来调整)
  15. rfm_model_df = rfm_model_df.reindex(columns=['R', 'F', 'M'])
  16. rfm_model_df

  1. # 将RFM模型的原始值处理成对应的等级
  2. def handle_r(value):
  3. if value <= 14:
  4. return 5
  5. elif value <= 30:
  6. return 4
  7. elif value <= 90:
  8. return 3
  9. elif value <= 180:
  10. return 2
  11. return 1
  12. def handle_f(value):
  13. if value >= 5:
  14. return 5
  15. return value
  16. def handle_m(value):
  17. if value < 500:
  18. return 1
  19. elif value < 800:
  20. return 2
  21. elif value < 1200:
  22. return 3
  23. elif value < 2500:
  24. return 4
  25. return 5
'
运行
  1. rfm_model_df['R'] = rfm_model_df.R.apply(handle_r)
  2. rfm_model_df['F'] = rfm_model_df.F.apply(handle_f)
  3. rfm_model_df['M'] = rfm_model_df.M.apply(handle_m)
  4. rfm_model_df.mean()

  1. rfm_model_df = (rfm_model_df > rfm_model_df.mean()).map(lambda x: '高' if x else '低')
  2. rfm_model_df

  1. rfm_model_df['Tag'] = rfm_model_df.sum(axis=1)
  2. rfm_model_df

  1. rfm_model_df['Tag'] = rfm_model_df.Tag.astype('category').cat.reorder_categories(
  2. ['高高高', '高低高', '低高高', '低低高', '高高低', '高低低', '低高低', '低低低']
  3. )
  4. result = rfm_model_df.Tag.value_counts().sort_index()
  5. result

  1. result.plot(
  2. kind='pie',
  3. autopct='%.2f%%',
  4. pctdistance=0.8,
  5. ylabel=''
  6. )
  7. plt.show()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/894596
推荐阅读
相关标签
  

闽ICP备14008679号