ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

口罩厂亏损分析

2021-02-23 22:04:18  阅读:270  来源: 互联网

标签:分析 口罩 数据 mask 亏损 pd csv data 缺失


文章目录

 


背景

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. 1、3、4 行完全重复
  2. 后 5 行数据的部分值是 NaN(NaN 代表缺失值,意思是这里的数据是空的)
  3. 数据中存在部分 0999999999.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('/Users/debroon/Desktop/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('/Users/debroon/Desktop/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。

数据中存在部分 0999999999.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('/Users/debroon/Desktop/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('/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['单价'] <= 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('/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['单价'] <= 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('/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['单价'] <= 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模型分析方法;
  • … …

数据展现

在分析完数据以后,需要通过表格或者图表的形式,直观、有效地传递出数据分析师所要表达的观点。

报告撰写

在对数据分析完并且展现完毕后,需要对整个过程进行一个梳理与总结。

标签:分析,口罩,数据,mask,亏损,pd,csv,data,缺失
来源: https://blog.csdn.net/qq_41739364/article/details/114001023

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有