背景
xx公司,运营了一家小型的口罩工厂,口罩厂经营状态过往处于不稳定的状态,在今年6月底,经营开始处于亏损状态。通过本次对口罩厂历史经营数据的分析,帮助公司推断口罩厂的发展,并对口罩厂的亏损问题处理提供建议。
明确目标
数据分析任务需要解决怎样的问题,以及该如何解决。
口罩厂从 2020 年初开始售卖口罩,到 7 月初的时候,总监发现账目上已经开始出现亏损。
总监十分焦虑,想要在短时间内快速找到亏损的原因,以及对应的解决策略。
- 找到亏损原因
- 找出对应的解决策略
具体怎么办呢?
数据分析一般来说会遵循五个步骤,分别是:
- 明确目标
- 数据处理
- 数据分析
- 数据展现
- 报告撰写
我们一步步走,你到底知不知道自己在解决什么问题。
请注意, 遇到具体问题时,你一定要问自己“我遇到的问题本质到底是什么?”
定义元问题
很多问题之所以难搞就是因为它特别的宏大而复杂,我们解决起来也不知道该从哪里入手。
为什么复杂问题我们总觉得解决起来就是千条万绪,找不到思路呢?这个答案很简单,也很重要。因为,我们生活当中遇到的大多问题都是所谓的复杂问题,而不是元问题。
什么是复杂问题呢?
- 就是掺杂了多个维度和变量的问题。
那什么是元问题?
- 就是那些最本质、最细小的待解决的问题。
复杂问题是不可直接解决的。
通过第一步【明确目标】的分析,已经知道了这次任务首先要做的就是找到口罩厂亏损背后的原因。
而亏损意味着利润为负,所以本质上我们要研究的是口罩厂的利润情况。
会影响口罩厂利润的因素有这些:
- 订单量
- 单价
- 成本
- 销售额
虽然知道了要素,但要素之间的连接关系彼此之间又存在一些关联,互相影响… …订单量要先影响销售额,然后销售额可能再进一步影响利润;但是销售额可能又会受到口罩单价等因素的影响。
这个时候你可能就会感到各种因素之间的关系非常乱,如果贸然地就对数据进行分析,很可能会有一种剪不断理还乱的困扰。
知道了这四个因素会影响口罩厂的利润,那接下来该如何动手去分析呢?
要想解决这种思路凌乱的问题,就需要借助分析框架,帮助我们系统地构建分析思路。
一般来说,我们会借助一些分析方法来搭建框架,比如逻辑树法、对比法、象限法、漏斗法等。
不过上面这些我都不用,因为有一种通用的分析框架:公式拆解法。
用公式思维拆解问题
其实,把一件事情公式化就是最好的拆解一件事情的方式。
有了这个公式以后,就相当于一个问题变成了元问题,现在大家就都知道了。
由于口罩厂的亏损本质上就是利润为负,那么利润就是最终想要研究的对象。
- 利润
最直接影响利润的因素是哪些?
- 利润 = 销售额(收入) - 成本
继续按照公式思维拆解【销售额】、【成本】。
销售额又会受到哪些因素直接影响?
- 销售额 = 总订单量 * 单价
总订单量还可以拆分为各个地方的订单量
- 总订单量 = 订单量(省份1) + 订单量(省份2) + 订单量(省份3)+ …
对销售额拆解后,我们应该思考成本会和哪些因素有关。
但总监说,2020 年 1 月到 6 月期间,各月成本几乎没有变化。
所以利润这个因素可以看作只受到销售额的影响,之后没有必要对成本继续拆解了。
P.S. 成本 = 人力成本 + 仓储物流成本 + 原材料成本;
接下来想问你一个问题,这四层信息足够支持我们找到口罩厂亏损背后的原因嘛?
不可以,总监是在 7 月初的时候发现了口罩厂出现了亏损,但是口罩厂是从 1 月初开始经营的。
我们需要通过这 6 个月来的数据变化情况,推演出口罩厂亏损的原因,所以,还需要一个时间维度(订单日期)的信息。
得到分析思路
说明:利润=销售额-成本,现已知 1-6
月份口罩成本是变动微小,故本次分析主要从“销售额(收入)”进行分析。
总方法:通过销售额及其影响因子的分析,对过往销售额变化的规律、变化原因进行剖析。
- 销售额 = 订单量 * 单价
- 订单量 = 省份1 + 省份2 … + 省份n
分析框架:
- 分析各月的“销售额”变化趋势,分析变化规律与原因。
- 分析各月“订单量”的变化趋势,分析变化规律与原因。
- 分析各月“单价”的变化趋势,分析变化规律与原因。
- 分析各月各省份“订单量”的变化趋势,分析变化规律及原因。
数据处理
在明确完目标以后,需要对数据进行清洗、整合等操作,把数据变成干净、规整的样子,这样后续才能对数据进行分析。
数据下载地址:https://download.csdn.net/download/qq_41739364/15437325
下载好后,我们就先从导入数据开始。
import pandas as pd
my_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
从公司数据库中导入营销数据mask_data.csv,原始数据一共包含 10,1942
行,数据的结构如下:
清理数据
我们仔细观察这份数据的前 5 5 5 行和后 5 5 5 行,看看它有没有什么不对的地方。
问题所在:
- 第
1、3、4
行完全重复 - 后 5 行数据的部分值是
NaN
(NaN 代表缺失值,意思是这里的数据是空的) - 数据中存在部分
0
和999999999.0
的数值( 999999999.0 999999999.0 999999999.0 接近十个亿,2019 年全国的口罩产能也才 50 50 50 亿, 10 10 10 个亿的订单我司口罩厂根本接不住,所以这里的数据也存在异常)
综上所述,这份数据同时存在缺失值、重复值以及异常值的问题,在进行数据处理时我们需要先将这些数据问题处理掉,这一过程也叫做【数据清洗】。
处理缺失值
在 pandas 库中,我们可以使用 isna()
方法来查找缺失值。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
print( mask_data.isna() )
# 查看 mask_data 的缺失值
isna()
返回都是布尔值:
- 缺失数据会用 T r u e True True 来表示
- F a l s e False False 则代表这里的数据不缺失
运行结果:
从结果中我们可以直接看到数据前后
5
5
5 行的缺失情况,其中
T
r
u
e
True
True 的位置表示该位置的数据为缺失值。
这里可能是数据采集时出了一些问题,对于缺失值,最简单的方法就是将含有缺失值的行直接删除。
当然除了删除之外还有其它处理方法,比如给缺失值填充数据。
由于我们总体的数据量比较大,缺失值占总数据量的比重也比较低,将含有缺失值的行删除后并不会妨碍后续的分析。
因此我们选择较为简易的处理方法,直接将含有缺失值的数据整行删除。
在 pandas 库中,我们可以使用 dropna() 方法删除含有缺失值的数据。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
print( mask_data.isna() )
# 查找缺失值
mask_data = mask_data.dropna()
# 删除缺失值,但dropna()并没有真正删除数据,只是返回一个删除了值的对象,所以重新赋值
print( mask_data.isna() )
# 查看 mask_data 的缺失值
到此,缺失值已经被处理干净了。
我们通常 info()
方法看一下这次删除了多少行数据,对总体数据影响大不大。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
print( mask_data.info() )
# 查看数据基本信息总结
mask_data.isna()
# 查找缺失值
mask_data = mask_data.dropna()
# 删除缺失值
print( mask_data.info() )
# 查看数据基本信息总结
处理缺失值前的数据:
处理缺失值后的数据:
这些输出是什么意思呢?
可以看到,与之前的数据的总量:
100956
100956
100956 与
101942
101942
101942 对比,我们删除了差不多
1000
1000
1000 行数据,不到总数据的
1
1
1% ,并不会对后续的分析产生太大影响。
处理重复值
重复值很好理解,就跟字面意思一样,指的是表格中重复出现的数据。在多数情况中,重复值都是完全相同的数据。
重复值处理的第一步和缺失值一样,还是要先查找重复值。
在 pandas 库中,我们可以直接使用 duplicated()
(中文意思:重复的)方法来查找重复数据,返回的是布尔值,重复为
T
r
u
e
True
True,不重复为
F
a
l
s
e
False
False。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
print( mask_data[mask_data.duplicated()] )
# 查找重复行
可以看到,这份数据中含有大量完全重复的行,这种重复数据并不具备分析的意义,而且会影响数据分析的结果,因此我们需要直接删除。
我们可以使用 pandas 库的 drop_duplicates()
方法删除重复出现的整行数据。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
print( mask_data[mask_data.duplicated()] )
# 查找重复行
在运行结果中我们能看见 mask_data
的表头下面是空的,说明到这里已经没有重复数据了。
最后我们再运行下方代码查看一下 mask_data
的基本信息总结。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
print( mask_data.info() )
# 查看数据基本信息总结
现在,数据的总量又变成了:
100508
100508
100508,相比于之前删完缺失值的数据:
100956
100956
100956,这次又删除了四百多行重复数据,大概占总数据的
0.4
0.4
0.4%,依然不会对分析结果造成太大影响。
处理异常值
首先我来快速跟你介绍一个检查数据是否存在异常的方法 —— describe()
。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
print( mask_data.describe() )
# 查看 mask_data 的描述性统计信息
describe()
方法返回出来的统计信息分别代表数值型数据的:
- 频数统计: c o u n t count count
- 平均值: m e a n mean mean
- 标准差: s t d std std
- 最小值: m i n min min
- 第一四分位数: 25 25 25%
- 中位数: 50 50 50%
- 第三四分位数: 75 75 75%
- 最大值: m a x max max
这里我们只需要观察最大最小值、平均数、中位数就好。
1.009560
e
+
09
1.009560e+09
1.009560e+09 代表的就是
1.009560
1.009560
1.009560 乘以
10
10
10 的
9
9
9 次方,也就是
999999999.0
999999999.0
999999999.0。
数据中存在部分 0
和 999999999.0
的数值,这就是异常值:
- 图中第1处:在实际业务中,不可能出现订单量为 0 0 0 的情况,所以订单量等于 0 0 0 的数据属于异常值。
- 图中第2处: 999999999.0 999999999.0 999999999.0 接近十个亿,2019 年全国的口罩产能也才 50 50 50 亿, 10 10 10 个亿的订单我司口罩厂根本接不住,所以这里的数据也存在异常。
- 图中第3处:单价的最大值也几乎是 10 的九次方。我们公司每盒口罩的单价最高 200 元,大于 200 的数据都属于异常值。
这些异常值会严重影响分析结果的准确性,所以我们需要在分析前抽取合理范围的数据,将异常值过滤掉。
在 pandas 库中,有一种筛选数据的方法叫做布尔索引。
比如我们想选择 mask_data 数据中,单价一列小于等于
200
200
200 的数据,就可以设置条件表达式 mask_data['单价'] <= 200
。
把它加入括号中索引:mask_data[mask_data['单价'] <= 200]
,就可以选取 mask_data 数据中单价这一列小于等于
200
200
200 的数据。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
print( mask_data[mask_data['单价'] <= 200] )
# 查看单价小于等于 200 的数据
怎么样?单价小于等于 200 的数据是不是显示了出来?这一操作就叫做布尔索引。
筛选单价小于等于 200 的数据后,再查看筛选后 mask_data 的描述性统计信息。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
mask_data = mask_data[mask_data['单价'] <= 200]
# 筛选单价小于等于 200 的数据
print( mask_data.describe() )
# 查看 mask_data 的描述性统计信息
清除异常值后,现在单价的最小值已经变成了 30,最大值变成了 200,在一个比较合理的范围内。平均值和中位数与之前比,也都变小、变合理了。
至此,这份数据中单价的异常值已经处理完毕,接下来我们再来看一下订单量一列的异常值。
仔细观察我们发现,订单量最大值变成了 100 100 100 ,比较合理。
说明上一步清除单价异常值的时候,订单量一列的最大值的异常也一并被处理掉了。
但订单量的最小值依然是 0 0 0 ,我们需要对 mask_data 中的’订单量’列数据再次进行筛选。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
mask_data = mask_data[mask_data['单价'] <= 200]
# 筛选单价小于等于 200 的数据
mask_data = mask_data[mask_data['订单量'] > 0]
# 筛选订单量大于0的数据
print( mask_data.describe() )
# 查看 mask_data 的描述性统计信息
可以看到订单量目前的范围在
1
1
1 至
100
100
100 之间,是一个较合理的订单量范围,我们不需要再进行数据筛选。
到这里,我们的这份数据就已经清洗完毕了。不过这并不意味着这份数据可以直接拿去分析。
在【明确目标】中分析,要先研究各个月的利润变化情况,所以我们需要将日期的统计数据由年-月-日调整为月,而后作为新的月份字段保存到数据中。
那么我们又该如何从日期这一列之中提取月份信息呢?
Python 中有一种专门储存时间日期的数据类型 —— datetime,我们可以直接从中提取想要的时间单位。
但 mask_data 中的日期列数据并不是 datetime 类型,而在 pandas 库中我们可以使用 to_datetime(arg, format)
方法转化为 datetime 类型。
- 其中的 arg 参数为我们要转换的数据,我们这次要转换的数据为 mask_data 中的’日期’字段,所以对应的 arg 参数就是 mask_data[‘日期’]
- format 参数为 datetime 类型的日期格式,比如说这份数据,它是以年-月-日的形式出现的,那么它对应的 format 就是 ‘%Y-%m-%d’
date_data = pd.to_datetime(mask_data['日期'], format = '%Y-%m-%d')
# 转换日期数据,并设置对应的日期格式
将’日期’字段转换成 datetime 类型后,我们就可以直接从中提取月份信息。
month_data = date_data.dt.month
# 提取日期数据中的月份信息
现在我们已经得到了所有的月份信息,最后一步,我们就可以将月份数据添加到原数据,方便之后使用。
在 pandas 库中,我们可以直接用 df[‘colname’] = Series 的方式来为原数据添加新的一列。
colname 指的是要添加的新列的列名。在这个案例中,colname 就是月份。
mask_data['月份'] = month_data
# 将月份数据添加到原数据中
完整代码:
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
mask_data = mask_data[mask_data['单价'] <= 200]
# 筛选单价小于等于 200 的数据
mask_data = mask_data[mask_data['订单量'] > 0]
# 筛选订单量大于0的数据
date_data = pd.to_datetime(mask_data['日期'], format = '%Y-%m-%d')
# 转换日期数据,并设置对应的日期格式
month_data = date_data.dt.month
# 提取日期数据中的月份信息
mask_data['月份'] = month_data
# 将月份数据添加到原数据中
print(mask_data)
清洗情况
清洗结果:我们对以上三种数据均进行了删除处理,其中清洗前数据一共有 101942 101942 101942,清洗后数据一共有 99485 99485 99485 行。
清洗数据占比:占比 2 2 2%
清洗前后数据量变化极小,因此可以忽略对结果的影响。
数据分析
在数据经过处理以后,就可以对数据进行分析,最终得到解决问题的策略。
数据分析,核心是分析思维。
分析思维不是要证明你智商很高,而是考察你面对问题展开的分析能力和分析思维。
书上的 5w2h
这样的常用分析方法,其实根本用不在数据分析工作里。
最常用的分析方法其实是:
- 多维度拆解分析方法;
- 对比分析方法;
- 假设检验分析方法;
- 相关分析方法;
- 群组分析方法;
- AARRR漏斗模型分析方法;
- RFM模型分析方法;
- … …
本次分析的影响因素是销售额、订单量、单价、各省订单量,而且是以一个月为颗粒度,进行时间维度上的变化趋势和原因分析。
以销售额为例,如果要分别查看 1 月到 6 月以来的销售额,可以根据月份对数据mask_data 进行分组。
如果每条记录都包含了一个销售额数值,那什么数值能够代表一整个月的销售额情况,能够用来与其他月进行比较呢?
我们可以计算出销售额的总数,因为它代表着这个月销售额的总体情况,可以通过对比它的上升或下降,查看其每月变化。
那如何得到每个月销售额总数呢?
首先要根据月份对数据集进行分组(groupby),同时还需要对销售额列进行一次聚合计算,计算出销售额的总和(sum)。
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
mask_data = mask_data[mask_data['单价'] <= 200]
# 筛选单价小于等于 200 的数据
mask_data = mask_data[mask_data['订单量'] > 0]
# 筛选订单量大于0的数据
date_data = pd.to_datetime(mask_data['日期'], format = '%Y-%m-%d')
# 转换日期数据,并设置对应的日期格式
month_data = date_data.dt.month
# 提取日期数据中的月份信息
mask_data['月份'] = month_data
# 将月份数据添加到原数据中
sales_income = mask_data.groupby('月份')['销售额'].sum()
# 获取每月销售额总数
print( sales_income )
根据数值已经可以大致看出,1-3 月总销售额增加, 3-6 月则在下降。基于这样的每月销售额统计数据,才能方便地进入后续趋势分析步骤中。
同理,依次按照此法,求出订单量、单价、各省订单量的变化规律。
order_number = mask_data.groupby('月份')['订单量'].sum()
# 获取各月总订单量
print( order_number )
不错,它同样能够体现出这个月所有订单量的变化情况,1-3 月数量上升,3-6 月数量下降。
month_price = mask_data.groupby('月份')['单价'].mean()
# 获取每月平均单价
print(month_price)
可以看到,终端打印出了每个月平均单价的不同数值,大致可以看出 1-3 月平均单价上升,3-6 月平均单价在下降。
month_order1 = mask_data.groupby(['省', '月份'])['订单量'].sum()
# 获取各月各省总订单量
print(month_order1)
省 月份
其他 1 452.0
2 10668.0
3 16871.0
4 2713.0
5 1250.0
6 113.0
广东 1 2628.0
2 77427.0
3 125618.0
4 46708.0
5 22364.0
6 4038.0
江苏 1 263.0
2 2530.0
3 4004.0
4 106.0
5 118.0
6 116.0
河南 1 434.0
2 10058.0
3 18293.0
4 2917.0
5 1239.0
6 107.0
湖北 1 9055.0
2 259511.0
3 1731060.0
4 476558.0
5 126342.0
6 17182.0
湖南 1 1020.0
2 29125.0
3 65634.0
4 17274.0
5 6875.0
6 666.0
完整代码:
import pandas as pd
mask_data = pd.read_csv('./mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
'''数据处理'''
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
mask_data = mask_data[mask_data['单价'] <= 200]
# 筛选单价小于等于 200 的数据
mask_data = mask_data[mask_data['订单量'] > 0]
# 筛选订单量大于0的数据
date_data = pd.to_datetime(mask_data['日期'], format = '%Y-%m-%d')
# 转换日期数据,并设置对应的日期格式
month_data = date_data.dt.month
# 提取日期数据中的月份信息
mask_data['月份'] = month_data
# 将月份数据添加到原数据中
'''数据分析'''
sales_income = mask_data.groupby('月份')['销售额'].sum()
# 获取每月销售额总数
order_number = mask_data.groupby('月份')['订单量'].sum()
# 获取各月总订单量
month_price = mask_data.groupby('月份')['单价'].mean()
# 获取每月平均单价
month_order1 = mask_data.groupby(['省', '月份'])['订单量'].sum()
# 获取各月各省总订单量
根据数据结果,我们其实可以大致看出数据变化的趋势。
但是其效果很不直观,需要人工比较数据、分析变化。所以下面正式进入变化趋势的分析,通过数据可视化来辅助我们的分析。
数据展现
在分析完数据以后,需要通过表格或者图表的形式,直观、有效地传递出数据分析师所要表达的观点。
import pandas as pd
mask_data = pd.read_csv('/Users/debroon/Desktop/mask_data.csv', encoding = 'utf-8')
# 导入 csv 数据
'''数据处理'''
mask_data = mask_data.dropna()
# 删除缺失值
mask_data = mask_data.drop_duplicates()
# 直接删除所有重复值
mask_data = mask_data[mask_data['单价'] <= 200]
# 筛选单价小于等于 200 的数据
mask_data = mask_data[mask_data['订单量'] > 0]
# 筛选订单量大于0的数据
date_data = pd.to_datetime(mask_data['日期'], format = '%Y-%m-%d')
# 转换日期数据,并设置对应的日期格式
month_data = date_data.dt.month
# 提取日期数据中的月份信息
mask_data['月份'] = month_data
# 将月份数据添加到原数据中
'''数据分析'''
sales_income = mask_data.groupby('月份')['销售额'].sum()
# 获取每月销售额总数
order_number = mask_data.groupby('月份')['订单量'].sum()
# 获取各月总订单量
month_price = mask_data.groupby('月份')['单价'].mean()
# 获取每月平均单价
month_order1 = mask_data.groupby(['省', '月份'])['订单量'].sum()
# 获取各月各省总订单量
'''数据展示'''
from matplotlib import pyplot as plt
# 导入matplotlib库的pyplot模块
plt.rcParams['font.family'] = ['Source Han Sans CN']
# 设置中文字体
sales_income.plot(kind = 'line', figsize = (7, 7), title = '各月总销售额趋势图')
# 画出各月总销售额的折线图
order_number.plot(kind = 'line', figsize = (7, 7), title = '各月总订单量趋势图')
# 画出各月总订单量的折线图
month_price.plot(kind = 'line', figsize = (7, 7), title = '各月平均单价趋势图')
# 画出各月平均单价的折线图
month_order1_df.plot(title='各月各省总订单量趋势图')
# 根据month_order1_df绘制多条折线图,标题为'各月各省总订单量趋势图'
可以发现无论各月的总销售额、总订单量、平均单价,以及各省在各月的总订单量,变化趋势有很大的相似性:
- 在 1 月到 3 月的折线是随着时间增长而增加,整体呈增加趋势,其中 2 月到 3 月增长快速;3 月之后整体呈下降趋势,3 月到 4 月出现了“急跌”。
- 目前的折线中未出现多个类似形状的起伏波动,未体现出任何规律性。
- 而且图中只有一处波动起伏,在这个起伏的最高点,对应着 3 月的数据,此处为最大值。
这种完全一致的变化趋势说明,此处总销售额的下降是由于订单量、单价双双下滑带来的,而非某一因素单方面的影响。
最后,我们来分析口罩厂各项影响因素的统计值都在“走下坡路”的原因,给总监一个“交代”。
报告撰写
在对数据分析完并且展现完毕后,需要对整个过程进行一个梳理与总结。
这里趋势变化非常明显,最大值(转折点)为 3 月,因此我们重点关注这个值,以其特殊性作为突破口。
根据订单量、单价的变化,我们可以知道,3 月之前,工厂的口罩需求量和价格都增长猛烈,3 月之后却又出现大幅下降。
按理来说,口罩属于医用防护品和日用生活品,不受季节、时间的影响。一般其需求源头比较稳定,物价也很稳定。
但是对比 1-3 月份总订单量的变化,其纵坐标的值是 0 到 2,但是单位是百万。因此是从 1 月份的万余盒,增长到 2 月份的 30 余万盒,突然涨到 3 月份 196 万余盒,变化迅猛。
另外通过折线图也能够发现趋势变化的强烈程度,比如 3 月到 4 月的订单量,就是一个“急跌”,订单量一下子缩水了 100 多万!
因此认为,要想在两三个月内迅速改变口罩的供需关系,应该是属于社会性问题的外部冲击。
与口罩使用的历史一致,几乎每次大的普及推广都是受传染性疾病或空气污染等外部影响。
因此这里排除业务内部原因,比如偶发性降价促销活动带来的客流量上涨与衰退,以及工厂竞争能力降低带来的市场占有率从高到低等等内部问题。
因为这些情况都属于常规运营问题,造成的影响远不会如此剧烈。
实际上,从 2020 年 1 月底开始,国内就蔓延出了新型冠状病毒疫情的传染性疾病,到了 3 月份,疫情感染人数才逐渐得到控制。
可以看到疫情出现与改善的时间,与以上所分析四个描述性统计数值的变化时间,整体上是非常吻合的。
疫情最严重的时期为 2 月份,2 月初电视中还经常出现药店口罩断供的新闻,3 月中下旬开始,全国陆续开始复工,人群流动性增加的情况下,口罩的需求也是达到了最高点。
而且我们也可以看到,各省的订单量变化中,以湖北省的变化最为强烈,在 2020 年的新冠疫情中,湖北省是重灾区,全省 5927 万人口,是非常大的需求缺口。
据说我们的工厂整个 2-3 月都在加班加点进行生产,但是口罩的价格与销量都还是只增不降,说明需求根本无法及时得到满足。
而到 3 月之后,疫情好转,全国各地陆续放松,尤其是不再要求必须在公众场合佩戴口罩,人们对于口罩的需求迅速回落,一直到 6 月销量和价格都仍在下落的过程中。
可以说,2020 年 1 月到 6 月,由于新冠疫情的影响,口罩的供需关系发生了很大的波动变化,导致工厂口罩的订单量、价格以及整体销售额也自然随之发生变化。
提出对策
说到问题根源,其实还是一个供需关系,如果口罩厂商在供需矛盾中不占优势,想要继续维持原来高价格高销量的情况几乎是不可能。
因为人们的购买标准,将从“能用”升级为性价比高、质量好、服务好等更复杂的行业竞争力问题上。
因此当疫情减少,刚性需求减少后,口罩行业的市场竞争将会越发激烈。
因疫情产生的刚性需求将回落为日常性需求,因此未来一段时间疫情稳定,订单量和单价不会同时上升。
如果这种状态下,6 月份口罩厂是处于亏损,那么未来这段时间,口罩厂将继续处于亏损状态。
基于这样的分析,我会跟总监提出两种不同的建议:
-
1)公司可以对口罩厂进行改革,不过对于工厂的优势,改革的重点及规划,还有待进一步对产品、营销体系等情况的分析。
-
2)如果公司不对口罩厂进行新的投入和改革,口罩厂将会持续亏损,建议尽早对口罩厂做转让处理。
当然,还有第三种方案,那就是基于国际局势考虑,目前南半球及欧美国家,由于气候及政策等原因,新冠疫情的危机是越演愈烈。
预计对于疫情为加重趋势的国家,口罩的需求量仍会比较高涨。
-
3)如果可以及时打开国际销售渠道,并维持相对较低的成本,工厂将仍能保持供需矛盾中的优势地位,维持高单价高销量的营收情况。