天猫订单数据分析
文章目录
- 项目介绍
- 数据介绍
- 工作概述
- 数据分析报告
- 数据分析过程
- 数据预处理
- 数据格式整理
- 异常值、重复值处理
- 数据分析
- 描述性统计分析
- 周趋势、日趋势分析
- 产品价格分析
- 转化率分析
项目介绍
本项目的数据为2020年2月份天猫某店铺的订单成交数据,共28010条。
数据介绍
数据集有以下7个字段:
- 订单编号:共28010条
- 总金额:该笔订单的总金额(下单后生成的金额,还未付款)
- 买家实际支付金额:实际成交金额,分为已付款和未付款两种情况:
- 已付款:买家实际支付金额 = 总金额 - 退款金额
- 未付款:买家实际支付金额 = 0
- 收货地址:单位为省份,共包含31个省、自治区、直辖市
- 订单创建时间:2020年2月1日 至 2020年2月29日
- 订单付款时间:2020年2月1日 至 2020年3月1日
- 退款金额:付款后申请退款的金额。(没有申请退款或没有付过款,退款金额为0)
工作概述
本人以促进产品销售为目的对项目数据进行分析操作,主要分析思想为结构分析、周期分析、比较分析、关联分析;通过数据分析,进而明确销售现状、挖掘潜在规律、发现存在问题、提出可行性建议,进而为优化经营起到助力作用。
具体工作做内容包括:数据清洗,异常值处理,概要性描述性分析,小时、日、周、月销售趋势分析、周期特点分析,退款及退款率分析、订单生命周期分析、销售额地域分布情况分析、产品价格分析、转化率分析等
工具:Python + (numpy + pandas + matplotlib +plotly + seaborn + pyecharts)库
数据分析报告
一、数据概述
2020年2月份本店产生的订单总量为:28009条,订单总金额:280.74万元;其中,实际完成销售的订单量为24087条,占比86%,实际产生销售收入的订单量为:18955条,占比67.67%,产生销售金额:190.25万元;流失订单的数量为9054条,占比32.33%,其中买家完全退款订单5646条,占总订单量的23.4%,退款金额合集为:50.23万;日均退款194.69单,退款金额1.97万元。(流失订单包括既没有支付也没有退款的订单,也包括下单后全部退款的订单,而下单后部分支付部分退款的订单不算在内)
从本月销售数据的波动情况来看,退款额和销售额在2月6日之后销售情况正常后成正相关关系,以及在可观测的时间段内我们的产品没有因为退款量过大而导致明显的销量下滑,这一方面说明市场对我们产品的需求相对稳定,也说明目前更有力的竞品还不多。
更值得我们注意的是,我们本月的流失订单高达9054条,基本是总订单量的三分之一,实售订单量的近二分之一,而其中用户完全退款的订单量为5646条,退款金额50.23万,是我们实售金额的四分之一。
之所以称这些订单为流失订单,是因为订单之所以能产生,说明用户对此类产品有需求,并在意识上选择了我们,有的甚至已经付款购买,但之后或者是因为对我们的产品、服务、物流、包装不满意,或者是认为竞品可以更好的替代等原因最终放弃了我们的产品,流向其他商家。
因此,我们必须及时采取措施加强对用户、产品、竞品的研究,找出我们退款率奇高的原因 (质量不达标、事物与图片不符、尺寸标注不当、包装不好导致商品破损、
快递过慢、发货出错、价格高于其他店铺…),并及时处理、优化,这样不仅眼下可以大幅降低退款率,提高销售收入,而且还可以进一步加强我们的品牌美誉度,
促进我们的产品更好的占领市场。否则,当有力的竞品涌入,或者当前竞品变得更有力的时候,我们的发展空间会被快速挤压。
二、订单分析:
1、订单与销售额结构分析:
- 本阶段分析的最小测量单位和后面的趋势分析统一于“小时”尺度,本阶段分析中的“时均量”由日均量/24小时得出;
将最小测量单位设定为小时,有利于大家对”流量“的概念有更直观的认识,在工作期间更认真、专注。 - 订单建立期指:订单从创建到完成支付所需的时长。
-
订单量:
- 总订单数为28009条,日均:965.82条,时均:40.24;其中买家实际付款的订单数为24087条,占比86%,日均:830.59条,时均:34.61条;
但是其中实际付款金额为0元的订单有5132条; - 有效订单——即买家实际支付金额不为0的订单为18955条(24087 - 5132),占总订单量的67.67%,约三分之二,日均:653.62条,时均:27.23条;
- 流失订单订单为9054条,占总订单量的32.33%,约三分之一,日均:312.21条,时均:13.01单。
买家退款订单5646条,占总订单量的23.4%,日均:194.69条,时均:8.11条(其中有514条退款是买家付款后产生的退款,占有效订单总量的2.71%;)。
- 总订单数为28009条,日均:965.82条,时均:40.24;其中买家实际付款的订单数为24087条,占比86%,日均:830.59条,时均:34.61条;
-
订单金额:
- 总金额:280.74万元,日均收入9.68万元,时均:0.4万元;其中实际收入(买家实际支付金额):190.25万元,占比67.76%,日均:6.56万元,时均:0.27万元;
流失订单金额90.50万元,占比32.23%,日均:3.12万元,时均:0.13万元;
其中退款金额为57.23万元,占比20.39%,日均:1.97万元,时均:0.08万元;
空单(有总金额,没有实际支付,也没有退款的订单)33.26万元,占比:11.85%,日均:1.15万元,时均:0.05万元; - 订单平均金额为100.2元,单笔最小金额1元,单笔最大金额16065元;
- 有效订单中,实际支付金额平均为100.36元,最小金额1元,最大金额16065元;
- 退款订单中,平均退款额为101.4元,最小1元,最大3800元;
- 总金额:280.74万元,日均收入9.68万元,时均:0.4万元;其中实际收入(买家实际支付金额):190.25万元,占比67.76%,日均:6.56万元,时均:0.27万元;
-
大部分订单金额在200元以下,20-175元的订单占了总订单量的近90%,其中以20-40元的订单量最多,占了总订单量的25%;
-
20元以下和175元以上的订单很少,占了总订单量的11%;
-
实际支付订单平均每单79.0元,最低1元。
-
订单建立期平均时长为6分39秒,最长23小时52分10秒,最短0秒,75分位数为13秒,时长很短。
因此可以推测本店产品大部分属于日常快消品,价格不贵,需求稳定。
订单建立周期短,大部分是下单直接付款,整个过程快速直接,没有逛淘宝时候放到购物车里隔几天集中结账这样的情况存在。
这种特点导致我们的营销方式适合简单直接的方式,而不是时下流行的”种草“。
三、以月、周、日为周期的数据分析
- 以月为周期来看,2月份前半月叠加春节假期和疫情防控,我店销售数据低迷,2月16日起随着复工复产逐步展开,我店销售数据也明显回升。
- 以周为周期来看,每周销售额最高的日子是周五,其次是周二,最差的是周一;周末销量比周一略高,低于其他工作日;
- 根据用户的一般日常活动来看,原因可能是工作日工作压力大,大家在这种情况下购买产品一方面是对产品有需求,另一方面,
这种消费多少也可以纾解一下工作日的压力,因此一般工作日的销售额会高于周末。 - 以日为周期来看,每日凌晨销量低,从6点开始销量稳定提升,中午开始趋于稳定略有波动,在10时、15时、21时分别有三个高峰,22点以后销量开始下降;
销量最高的时间是晚上21点,而20点、21点、22点是销量最高的时段,这和电视剧的黄金档时间重合,这是人们工作日娱乐的主要时间段。
四、各区域销售情况分析
- 销售额最高的地区是上海;
- 北京、江苏、广东、浙江为第二梯队;
- 销售额高的地区主要集中在东南沿海的发达经济区,以及西南的政治经济中心四川省;
- 销售额最少的地区为:西藏、青海、新疆、宁夏等西部欠发达地区和目前的疫情中心——湖北。
五、相关建议:
- 目前疫情已经常态化,应该准备针对疫情局部爆发的应急预案,并对日常工作进行调整;一方面能保证在有疫情影响的状态下仍能有序接受订单,
另一方面也要考虑适量生产,避免产生因疫情导致的产品积压情况出现。 - 促销信息、产品推广时间最好安排在晚上20点—22点,对我们的产品来说,这是达成销售最好的时段,也是用户浏览娱乐、消费信息的主要时段,
除了可以扩大销量外,也可以促进商品信息的人际传播,有条件多次推送的话10点,15点也可以考虑尝试。 - 促销活动可以安排在周五,该日的销售额最高,也就是说我们的商品信息在周五触达用户最有效,因此传播效率最高、促销效果较其他日子更好。
- 产品推广以价格20-45元和100-125元的产品为主,20-40元的商品利润应该不高,但由于价格又好可以扩大市场占有率,但可以增加用户粘性,扩大品牌知名度;
100-125元的产品也比较受欢迎,利润应该也相对好一些,可以作为金牛产品增加收入。 - 销售额的区域分布和各地区的经济发达程度程正相关关系。湖北省当时处于疫情中心,由于社会运转暂停,销售额偏低属于正常情况。
目前销量最高的产品价格集中在20-125元,尤其是20-40元,产品价格不高,但是对西部省份不包邮,因而由于成本约束,短期很难提高西部各省份的销量,
所以可以优先考虑提高西南、东北、华中地区的销量,逐步寻找发展西部地区销量的对策。在第二梯队地区及非西部地区持续发力促销,扩大市占率,
并对其他地区形成正面影响,比如,北京之于北方,广东之于闽桂湘、四川之于云贵藏、江浙之于鲁赣皖等。 - 重中之重,还是尽量想办法减少订单流失,降低退款率。
数据分析过程
导入相关库
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
from plotly.offline import download_plotlyjs, init_notebook_mode
init_notebook_mode(connected = True)
import plotly as py
import plotly.graph_objs as go
pyplot = py.offline.iplot
sns.set()
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["font.family"] = 'Arial Unicode MS'
plt.rcParams['font.sans-serif']=['AR PL UMing CN']
from pyecharts.globals import CurrentConfig, NotebookType
CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_LAB
#在mac系统中设置中文字体
from matplotlib.font_manager import FontManager
fm = FontManager()
fonts = set(f.name for f in fm.ttflist)
读入数据并查看概况
data = pd.read_csv("tmall_order_report.csv")
data.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
结果显示,数据共有7个维度,其中“订单付款时间”的非空计数少于28010,需要对缺失值进行处理;另外2个时间的数据类型不适合分析需要修改。
data.sample(10)
以上为数据抽样,在接下来的分析中我们可以对数据进行周期分析,也就是按照月、周、日、小时等周期进行分析,并且需要对用户地区,退款,每单平均金额等因素进行分析;因此在数据预处理阶段也需要按照这些要求对数据进行处理。
data.describe()
订单编号 | 总金额 | 买家实际支付金额 | 退款金额 | |
---|---|---|---|---|
count | 28010.000000 | 28010.000000 | 28010.000000 | 28010.000000 |
mean | 14005.500000 | 106.953253 | 67.921712 | 20.433271 |
std | 8085.934856 | 1136.587094 | 151.493434 | 71.501963 |
min | 1.000000 | 1.000000 | 0.000000 | 0.000000 |
25% | 7003.250000 | 38.000000 | 0.000000 | 0.000000 |
50% | 14005.500000 | 75.000000 | 45.000000 | 0.000000 |
75% | 21007.750000 | 119.000000 | 101.000000 | 0.000000 |
max | 28010.000000 | 188320.000000 | 16065.000000 | 3800.000000 |
数据预处理
数据格式整理
规范字段名
data.columns
Index(['订单编号', '总金额', '买家实际支付金额', '收货地址 ', '订单创建时间', '订单付款时间 ', '退款金额'], dtype='object')
查看文件各字段,结果显示,"收货地址"和“订单付款金额”连个字段后面跟有空格,需要进行规范处理。
#修改有问题字段,rename
data.rename(columns={
'收货地址 ': '收货地址', '订单付款时间 ':'订单付款时间'}, inplace=True)
# 检查修改结果
data.columns
Index(['订单编号', '总金额', '买家实际支付金额', '收货地址', '订单创建时间', '订单付款时间', '退款金额'], dtype='object')
修改时间的数据类型
'订单付款时间’和’订单创建时间’的类型是object, 将其改成日期格式,以便后期分析时使用。
data['订单创建时间'] = pd.to_datetime(data['订单创建时间'])
data['订单付款时间'] = pd.to_datetime(data['订单付款时间'])
data.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 datetime64[ns]
5 订单付款时间 24087 non-null datetime64[ns]
6 退款金额 28010 non-null float64
dtypes: datetime64[ns](2), float64(3), int64(1), object(1)
memory usage: 1.5+ MB
修改成功,两字段已经变成了datetime64类型数据
增加分析要使用的字段
为了精细化分析,在“订单创建时间”和“订单付款时间”两个维度增加日、星期、时刻等字段
data['创建时间'] = data['订单创建时间'].dt.strftime('%m月%d日')
data['付款时间'] = data['订单付款时间'].dt.strftime('%m月%d日')
data.head()
订单编号 | 总金额 | 买家实际支付金额 | 收货地址 | 订单创建时间 | 订单付款时间 | 退款金额 | 创建时间 | 付款时间 | |
---|---|---|---|---|---|---|---|---|---|
0 | 1 | 178.8 | 0.0 | 上海 | 2020-02-21 00:00:00 | NaT | 0.0 | 02月21日 | NaN |
1 | 2 | 21.0 | 21.0 | 内蒙古自治区 | 2020-02-20 23:59:54 | 2020-02-21 00:00:02 | 0.0 | 02月20日 | 02月21日 |
2 | 3 | 37.0 | 0.0 | 安徽省 | 2020-02-20 23:59:35 | NaT | 0.0 | 02月20日 | NaN |
3 | 4 | 157.0 | 157.0 | 湖南省 | 2020-02-20 23:58:34 | 2020-02-20 23:58:44 | 0.0 | 02月20日 | 02月20日 |
4 | 5 | 64.8 | 0.0 | 江苏省 | 2020-02-20 23:57:04 | 2020-02-20 23:57:11 | 64.8 | 02月20日 | 02月20日 |
#创建weekday,用来将日期(date)转换成对应的星期(day)
def to_weekday(a):
result=np.nan
if a == 0:
result = '周一'
elif a == 1:
result = '周二'
elif a == 2:
result = '周三'
elif a == 3:
result = '周四'
elif a == 4:
result = '周五'
elif a == 5:
result = '周六'
elif a == 6:
result = '周日'
return result
data['订单创建时间'].dt.weekday.sample(5)
23110 4
4461 3
20981 5
4912 2
20680 5
Name: 订单创建时间, dtype: int64
data['订单创建时间'].dt.hour.sample(5)
27304 11
3510 21
26672 16
16743 16
27392 11
Name: 订单创建时间, dtype: int64
data['创建星期'] = data['订单创建时间'].dt.weekday.apply(to_weekday)
data['创建时刻'] = data['订单创建时间'].dt.hour
data['付款星期'] = data['订单付款时间'].dt.weekday.apply(to_weekday)
data['付款时刻'] = data['订单付款时间'].dt.hour
data.sample(8)
订单编号 | 总金额 | 买家实际支付金额 | 收货地址 | 订单创建时间 | 订单付款时间 | 退款金额 | 创建时间 | 付款时间 | 创建星期 | 创建时刻 | 付款星期 | 付款时刻 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
24417 | 24418 | 192.0 | 192.0 | 山东省 | 2020-02-28 13:20:48 | 2020-02-28 13:21:06 | 0.0 | 02月28日 | 02月28日 | 周五 | 13 | 周五 | 13.0 |
5218 | 5219 | 154.4 | 154.4 | 上海 | 2020-02-04 12:59:18 | 2020-02-04 12:59:24 | 0.0 | 02月04日 | 02月04日 | 周二 | 12 | 周二 | 12.0 |
5694 | 5695 | 76.0 | 0.0 | 上海 | 2020-02-02 21:45:45 | 2020-02-02 21:45:54 | 76.0 | 02月02日 | 02月02日 | 周日 | 21 | 周日 | 21.0 |
26688 | 26689 | 69.0 | 69.0 | 海南省 | 2020-02-27 16:26:38 | 2020-02-27 16:27:58 | 0.0 | 02月27日 | 02月27日 | 周四 | 16 | 周四 | 16.0 |
20683 | 20684 | 69.0 | 0.0 | 山东省 | 2020-02-29 23:20:35 | NaT | 0.0 | 02月29日 | NaN | 周六 | 23 | NaN | NaN |
10231 | 10232 | 69.0 | 69.0 | 陕西省 | 2020-02-22 00:32:11 | 2020-02-22 00:32:29 | 0.0 | 02月22日 | 02月22日 | 周六 | 0 | 周六 | 0.0 |
5221 | 5222 | 108.0 | 0.0 | 广东省 | 2020-02-04 12:59:06 | 2020-02-04 12:59:11 | 108.0 | 02月04日 | 02月04日 | 周二 | 12 | 周二 | 12.0 |
22761 | 22762 | 37.0 | 37.0 | 浙江省 | 2020-02-28 23:50:03 | 2020-02-28 23:50:13 | 0.0 | 02月28日 | 02月28日 | 周五 | 23 | 周五 | 23.0 |
简化地址
简化收货地址的省、自治区、直辖市名称,方便后续查看。
简化前
data['收货地址'].unique()
array(['上海', '内蒙古自治区', '安徽省', '湖南省', '江苏省', '浙江省', '天津', '北京', '四川省',
'贵州省', '辽宁省', '河南省', '广西壮族自治区', '广东省', '福建省', '海南省', '江西省', '甘肃省',
'河北省', '黑龙江省', '云南省', '重庆', '山西省', '吉林省', '山东省', '陕西省', '湖北省',
'青海省', '新疆维吾尔自治区', '宁夏回族自治区', '西藏自治区'], dtype=object)
简化后
data['收货地址'] = data['收货地址'].str.replace('省', '').str.replace('自治区', '')
data['收货地址'] = data['收货地址'].str.replace('壮族', '').str.replace('维吾尔族', '').str.replace('回族', '')
data['收货地址'].unique()
array(['上海', '内蒙古', '安徽', '湖南', '江苏', '浙江', '天津', '北京', '四川', '贵州', '辽宁',
'河南', '广西', '广东', '福建', '海南', '江西', '甘肃', '河北', '黑龙江', '云南', '重庆',
'山西', '吉林', '山东', '陕西', '湖北', '青海', '新疆维吾尔', '宁夏', '西藏'],
dtype=object)
缺失值处理
data.isnull().sum()
订单编号 0
总金额 0
买家实际支付金额 0
收货地址