该数据集来源于网络,敏感数据均已脱敏。该数据集描述的是天猫2020年2月份的真实交易数据。
import pandas as pd
import numpy as np
import datetime as dt
import math
from pyecharts.charts import Bar, Grid, Line, Pie, Tab, Funnel, Map
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
# 配置
file=r'D:\Python\e-commerce\tmall_order_report.csv'
blue_list=["#0f2350", "#1e50a2", "#007bbb", "#2ca9e1"]
dict_area={
'广西壮族自治区':'广西',
'内蒙古自治区':'内蒙古',
'新疆维吾尔自治区':'新疆',
'宁夏回族自治区':'宁夏',
'西藏自治区':'西藏',
}
# 预处理
df_origin=pd.read_csv(file)
# 自定义函数
def get_number(list_x=[],num_type=int):
return [num_type(x) for x in list_x]
df_origin.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 28010 entries, 0 to 28009 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 订单编号 28010 non-null int64 1 总金额 28010 non-null float64 2 买家实际支付金额 28010 non-null float64 3 收货地址 28010 non-null object 4 订单创建时间 28010 non-null object 5 订单付款时间 24087 non-null object 6 退款金额 28010 non-null float64 dtypes: float64(3), int64(1), object(3) memory usage: 1.5+ MB
df_origin.sample()
df_origin.describe()
# 清洗
df_origin.columns=[i.strip() for i in df_origin.columns]
df_origin['订单创建时间']=df_origin['订单创建时间'].apply(lambda x:dt.datetime.strptime(x,'%Y-%m-%d %H:%M:%S'))
df_origin['订单付款时间']=df_origin['订单付款时间'].apply(lambda x:dt.datetime.strptime(x,'%Y-%m-%d %H:%M:%S') if pd.notnull(x) else x)
df_origin['创建时间_日期']=df_origin['订单创建时间'].apply(lambda x:dt.date(x.year,x.month,x.day))
df_origin['创建时间_时']=df_origin['订单创建时间'].apply(lambda x:x.hour)
df_origin['收货地址']=df_origin['收货地址'].apply(lambda x:dict_area[x] if x in dict_area.keys() else x)
df_origin['收货地址']=df_origin['收货地址'].apply(lambda x:x.replace('省',''))
# 添加辅助列 - 订单状态
# 1:待支付,2:成功交易,3:部分退款,4:全部退款
df_origin.loc[df_origin['订单付款时间'].isnull(),'状态']=1
df_origin.loc[(df_origin['订单付款时间'].notnull())&(df_origin['退款金额']==0),'状态']=2
df_origin.loc[(df_origin['买家实际支付金额']!=0)&(df_origin['退款金额']!=0),'状态']=3
df_origin.loc[(df_origin['买家实际支付金额']==0)&(df_origin['退款金额']!=0),'状态']=4
# 1-1 交易数据
c1_data=df_origin['状态'].value_counts().sort_index()
c1_data.value=[int(x) for x in c1_data.values]
c1=Pie(init_opts=opts.InitOpts(width="1200px", height="600px"))
c1.add("",
[list(z) for z in zip(['待支付','成功交易','部分退款','全部退款'],
[int(x) for x in c1_data.values])],
center=["25%", "50%"],
radius=[0, 200],)
c1.set_colors(blue_list)
c1.set_global_opts(title_opts=opts.TitleOpts(title="订单数量分布 | 订单金额分布"))
c2_data=pd.pivot_table(df_origin,
values='总金额',
index='状态',
aggfunc=sum).sort_index()
c1.add("",
[list(z) for z in zip(['待支付','成功交易','部分退款','全部退款'],
[int(x) for x in c2_data.values])],
center=["75%", "50%"],
radius=[0, 200],)
c1.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}({d}%)"))
c1.render_notebook()
2020年2月份,订单总数为28010单,其中完全成交订单数量为18441单,占比约为66%;订单总金额约为300万,其中完全成交金额为186万,占比约为62%。发生退款行为的订单中,完全退款的占比较多。
# 1-2 转化漏斗
c3_data=[c1_data.sum(),c1_data[2:].sum(),c1_data[3:].sum()]
c3_data=[int(x) for x in c3_data]
fn="""
function(params) {
return params.name + ': ' + params.value + '(' +
Math.round(params.value/"""+str(c3_data[0])+"""*100) +'%)';
}
"""
c3=Funnel(init_opts=opts.InitOpts(width="1200px", height="600px"))
c3.add("",[list(z) for z in zip(['下单','付款','退款'], c3_data)])
c3.set_series_opts(label_opts=opts.LabelOpts(formatter=JsCode(fn),
position="inside"))
c3.render_notebook()
从下定到付款的转化率约为86%。发生退款的订单占比约为20%。
# 1-3 付款时效
df_payed=df_origin[df_origin['订单付款时间'].notnull()].reset_index(drop=True)
df_payed['付款时效']=df_payed['订单付款时间']-df_payed['订单创建时间']
df_payed['付款时效']=df_payed['付款时效'].apply(lambda x:x.seconds)
c4_date=df_payed['付款时效'].value_counts().sort_index()
c4=Bar(init_opts=opts.InitOpts(width="1200px", height="600px"))
c4.add_xaxis(list(c4_date.index))
c4.add_yaxis("订单数",[int(x) for x in c4_date.values])
c4.set_global_opts(title_opts=opts.TitleOpts(title="付款时效分布图"),
datazoom_opts=opts.DataZoomOpts(range_start=0,
range_end=8),
yaxis_opts=opts.AxisOpts(name='时间:秒'))
c4.render_notebook()
从时效上来看,从下订单到付款一般不会超过15秒,即下单后短时间内马上会付款。
# 2-1 时间序列
c5_bill_day=pd.pivot_table(df_origin,
index='创建时间_日期',
values='订单编号',
aggfunc=len).sort_index()
c5_bill_hour=pd.pivot_table(df_origin,
index='创建时间_时',
values='订单编号',
aggfunc=len).sort_index()
c5_payment_day=pd.pivot_table(df_origin,
index='创建时间_日期',
values='总金额',
aggfunc=sum).sort_index()
c5_payment_hour=pd.pivot_table(df_origin,
index='创建时间_时',
values='总金额',
aggfunc=sum).sort_index()
c5_payment_day=round(c5_payment_day/10000,2)
c5_payment_hour=round(c5_payment_hour/10000,2)
c5=Tab()
c5_bill=Grid(init_opts=opts.InitOpts(width="1200px", height="600px"))
c5_payment=Grid(init_opts=opts.InitOpts(width="1200px", height="600px"))
c51_day=Line()
c51_hour=Line()
c52_day=Line()
c52_hour=Line()
c51_day.add_xaxis(list(c5_bill_day.index))
c51_day.add_yaxis("订单数",
get_number(c5_bill_day.values),
is_smooth=True,
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]),)
c51_day.set_global_opts(title_opts=opts.TitleOpts(title="订单数 - 日期趋势"))
c51_day.set_series_opts(markarea_opts=opts.MarkAreaOpts(
data=[
opts.MarkAreaItem(name='春节假期',
x=(dt.date(2020,2,11),
dt.date(2020,2,17))
)
]
))
c5_bill.add(c51_day,grid_opts=opts.GridOpts(pos_bottom="60%"))
c51_hour.add_xaxis(list(c5_bill_hour.index))
c51_hour.add_yaxis("订单数",
get_number(c5_bill_hour.values),
is_smooth=True,
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]),)
c51_hour.set_global_opts(title_opts=opts.TitleOpts(title="订单数 - 时间趋势",
pos_top="48%"),
legend_opts=opts.LegendOpts(is_show=False))
c5_bill.add(c51_hour,grid_opts=opts.GridOpts(pos_top="60%"))
c52_day.add_xaxis(list(c5_payment_day.index))
c52_day.add_yaxis("订单金额",
get_number(c5_payment_day.values,float),
is_smooth=True,
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]),)
c52_day.set_global_opts(title_opts=opts.TitleOpts(title="订单金额 - 日期趋势"),
yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value}万")),)
c52_day.set_series_opts(markarea_opts=opts.MarkAreaOpts(
data=[
opts.MarkAreaItem(name='春节假期',
x=(dt.date(2020,2,11),
dt.date(2020,2,17))
)
]
))
c5_payment.add(c52_day,grid_opts=opts.GridOpts(pos_bottom="60%"))
c52_hour.add_xaxis(list(c5_payment_hour.index))
c52_hour.add_yaxis("订单金额",
get_number(c5_payment_hour.values,float),
is_smooth=True,
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]),)
c52_hour.set_global_opts(title_opts=opts.TitleOpts(title="订单金额 - 时间趋势",
pos_top="48%"),
legend_opts=opts.LegendOpts(is_show=False))
c5_payment.add(c52_hour,grid_opts=opts.GridOpts(pos_top="60%"))
c5.add(c5_bill,'订单数')
c5.add(c5_payment,'订单金额')
c5.render_notebook()
从日期来看,年前用户没有什么购物的欲望,在春节假期进入了低谷。但走出春节假期后,用户会开始消费,在月底时达到了高点。
时间上来看,用户会比较倾向于在晚上购物(7点-9点为购物高峰)。
# 2-2 地域分布
c6=Tab()
c6_bill_data=pd.pivot_table(df_origin,
index='收货地址',
values='订单编号',
aggfunc=len).sort_values(['订单编号'],ascending=False)
c6_payment_data=pd.pivot_table(df_origin,
index='收货地址',
values='总金额',
aggfunc=sum).sort_values(['总金额'],ascending=False)
c6_payment_data=round(c6_payment_data/10000,2)
c6_bill=Map(init_opts=opts.InitOpts(width="1200px", height="600px"))
c6_bill.add('订单数',
[list(z) for z in zip(c6_bill_data.index,
get_number(c6_bill_data.values))],
"china",)
c6_bill.set_global_opts(title_opts=opts.TitleOpts(title='全国订单数量分布'),
visualmap_opts=opts.VisualMapOpts(max_=math.ceil(max(c6_bill_data.values)[0]/500)*500))
c6_payment=Map(init_opts=opts.InitOpts(width="1200px", height="600px"))
c6_payment.add('订单金额',
[list(z) for z in zip(c6_payment_data.index,
get_number(c6_payment_data.values,float))],
"china",)
c6_payment.set_global_opts(title_opts=opts.TitleOpts(title='全国订单金额分布'),
visualmap_opts=opts.VisualMapOpts(max_=math.ceil(max(c6_payment_data.values)[0]/5)*5))
c6.add(c6_bill,'订单数量分布')
c6.add(c6_payment,'订单金额分布')
c6.render_notebook()
北京、山东、长三角地区(江浙沪皖)、广东和四川地区的用户购买力较强,消费金额最多的是上海。
# 2-3 退款率排行
refund=pd.pivot_table(df_origin[df_origin['状态'].isin([3,4])],
index='收货地址',
values='订单编号',
aggfunc=len).sort_values(['订单编号'],ascending=False)
refund=pd.merge(refund,
c6_bill_data,
how='outer',
left_index=True,
right_index=True)
refund.columns=['退款订单数','订单总数']
refund['退款率']=round(refund['退款订单数']/refund['订单总数']*100,2)
refund.sort_values(['退款率'],ascending=False,inplace=True)
c7=Bar(init_opts=opts.InitOpts(width="1200px", height="600px"))
c7.add_xaxis(list(refund.index))
c7.add_yaxis('退款订单数',
get_number(refund['退款订单数'].values),
label_opts=opts.LabelOpts(is_show=False),)
c7.add_yaxis('订单总数',
get_number(refund['订单总数'].values),
label_opts=opts.LabelOpts(is_show=False),)
c7.extend_axis(
yaxis=opts.AxisOpts(
name='占比',
axislabel_opts=opts.LabelOpts(formatter="{value}%",)
)
)
c7.set_global_opts(
title_opts=opts.TitleOpts(title="各地区退款率排行"),
datazoom_opts=opts.DataZoomOpts(range_start=0,
range_end=math.floor(10/refund.shape[0]*100)),
tooltip_opts=opts.TooltipOpts(is_show=True,
trigger="axis",
axis_pointer_type="cross"),
xaxis_opts=opts.AxisOpts(
type_="category",
axispointer_opts=opts.AxisPointerOpts(is_show=True, type_="shadow"),
),
yaxis_opts=opts.AxisOpts(
name='订单数',
axistick_opts=opts.AxisTickOpts(is_show=True),
splitline_opts=opts.SplitLineOpts(is_show=True),
)
)
c7_line=Line()
c7_line.add_xaxis(list(refund.index))
c7_line.add_yaxis('退款率',
y_axis=(get_number(refund['退款率'])),
yaxis_index=1,
is_smooth=True,
z_level=1,
label_opts=opts.LabelOpts(formatter=JsCode("function(x){return x.data[1]+'%'}"),)
)
c7.overlap(c7_line)
c7.render_notebook()
虽然西藏地区发生的退款率最高,但订单数量较少,可以忽略。其次为湖北、新疆地区,需要重点关注。其他地区的退款率基本保持在25%以下。
1、交易:
2020年2月份,订单总数为28010单,其中完全成交订单数量为18441单,占比约为66%;订单总金额约为300万,其中完全成交金额为186万,占比约为62%。
订单转化率约为86%。发生退款的订单占比约为20%。
2、用户行为:
消费主力用户分布在北上广深、长三角地区、广东和四川。
用户在春节假期过完后,交易行为逐渐达到了峰值。用户会倾向于在工作时间的10点、15点和晚上购物,但购物高潮是在晚上的19点左右。