运用python中的numpy、pandas等包,可以帮助我们很方便的进行数据统计、数据分析。今天,通过朝阳医院2018的销售数据这个案例来简单做一下展示。

数据分析的基本过程一般分为以下几个部分:

提出问题、理解数据、数据清洗、构建模型、数据可视化。

现在从第一步开始着手。

1.提出问题

在数据分析之前,我们先要明确分析目标是什么,这样可以避免我们像无头苍蝇一样拿着数据无从下手,也可以帮助我们更高效的选取数据,进行分析研究。

本次的分析目标是从销售数据中分析出以下业务指标:

1)月均消费次数

2)月均消费金额

3)客单价

4)消费趋势

有了分析目标,我们再来关注一下数据情况。

2.理解数据

1)导入数据包,提取数据文件

在提取数据中,为了保证数据文件中的数据读取正常,通常会将函数的dtype参数设置成'object'。 object的意思是统一按照字符串的格式来读取数据。

#导入numpy、pandas包

import numpy as np

import pandas as pd

#导入数据

xls = pd.ExcelFile(r'D:\dataFile\朝阳医院2018年销售数据.xlsx', dtype='object')

salesDf = xls.parse('数据1',dtype='object')

#当excel中只有一个数据工作表时,用下面的函数直接读取数据也可以。

#salesDf = pd.read_excel(r'D:\dataFile\朝阳医院2018年销售数据.xlsx', dtype='object')

2)查看导入数据的基本状况

#查看导入数据的类型

type(salesDf)

pandas.core.frame.DataFrame

#查看导入数据的每个项目的类型

salesDf.dtypes

购药时间 object

社保卡号 object

商品编码 object

商品名称 object

销售数量 object

应收金额 object

实收金额 object

dtype: object

#查看数据的基本大小

salesDf.shape

(6578, 7)

#查看开头几行数据,看看数据是否读取正确

salesDf.head()

#用描述函数describ来查看一下整个数据的基本状况

salesDf.describe()

从这些函数中,我们可以基本了解到数据由购药时间、社保卡号、商品编码、商品名称、销售数量、应收金额、实收金额这七个基本项目组成,数据条数为6578条。

3.数据清洗

取得了数据,并不能马上就开始进行数据分析。我们得到的数据通常并不是完全符合我们分析要求的,而且可能存在缺失值、异常值,这些数据都会使我们的分析结果产生偏差。所以在分析之前,需要进行子集选择、缺失数据补充、异常值处理、数据类型转换等多个步骤。这些都属于数据清理的范畴。

在数据分析中,通常有多达60%的时间是花在数据清洗中的。通常的清洗步骤有以下几步:

• 选择子集

• 列名重命名

• 缺失数据处理

• 数据类型转换

• 数据排序

• 异常值处理

这些步骤有些不是一步就能完成的,可能需要重复操作。

现在开始对药店销售数据进行数据清洗。

1)选择子集

药店销售数据中,项目较少,选择子集可以忽略,我们从列名重命名开始。

2)列名重命名

销售数据集,购药时间显示为销售时间更为合理,我们先把这个项目名称做一下变更。

#购药时间->销售时间

nameChangeDict = {'购药时间':'销售时间'}

#参数inplace=True表示覆盖元数据集

salesDf.rename(columns = nameChangeDict,inplace=True)

现在再来显示一下数据,可以发现购药时间已经变成了销售时间。

salesDf.head()

3)缺失数据处理

对于缺失数据,我们可以有几种处理方法:

▪ 删除

当缺失数据占总数据量的比例很小的时候,我们通常采用删除的处理方法。

▪ 合理值填充

在某些不适合删除的场合,我们有时候也会对缺失数据进行合理值填充,如平均值,中位数,相邻数据等等。

#首先查看一下哪些项目存在缺失值

salesDf.isnull().any()

销售时间 True

社保卡号 True

商品编码 True

商品名称 True

销售数量 True

应收金额 True

实收金额 True

dtype: bool

好吧,每个项目都存在缺失值。在这个销售数据中,销售时间和社保卡号是必须项目,不可或缺。所以我们在这里只把销售时间和社保卡号有缺失的数据做删除处理。我们来查看一下销售时间和社保卡缺失的数据大小,然后做删除处理。

#查看一下缺失值的数量

#通常可以用isnull函数来查找缺失值

salesDf[salesDf[['销售时间','社保卡号']].isnull().values == True]

#序号6574因为销售时间和社保卡号都缺失,所以会出现两次。所以我们要去掉一下重复数据。

naDf = salesDf[salesDf[['销售时间','社保卡号']].isnull().values == True].drop_duplicates()

naDf

从上面可以清楚看出销售时间和社保卡号缺失的数据一共有三条,当数据量大的时候我们可以只显示条数,不显示数据内容

#缺失数据行数

naDf.shape[0]

3

现在把这些缺失数据进行删除

#删除前数据集规模显示

salesDf.shape

(6578, 7)

#含有销售时间和社保卡号的缺失数据删除

salesDf = salesDf.dropna(subset=['销售时间','社保卡号'],how = 'any')

#删除后数据集规模显示

salesDf.shape

(6575, 7)

在数据删除后要及时更新一下最新的序号,不然可能会产生问题。我开始做的时候,在这里没有更新数据序号,导致后续销售时间数据类型用函数转换后与元数据合并时发生了错位,数据发生了新的缺失,后来发现导致问题产生的原因在这里。

#重命名行名(index):排序后的列索引值是之前的行号,需要修改成从0到N按顺序的索引值

salesDf=salesDf.reset_index(drop=True)

4)数据类型转换

▪ 数量、金额项目:从字符串类型转换为数值(浮点型)类型

salesDf['销售数量'] = salesDf['销售数量'].astype('float')

salesDf['应收金额'] = salesDf['应收金额'].astype('float')

salesDf['实收金额'] = salesDf['实收金额'].astype('float')

print('转换后的数据类型:\n',salesDf.dtypes)

转换后的数据类型:

销售时间 object

社保卡号 object

商品编码 object

商品名称 object

销售数量 float64

应收金额 float64

实收金额 float64

dtype: object

▪ 日期项目:从字符串类型转换为日期类型

销售日期中包含了日期和星期,我们只要保留日期内容即可。这里用一个自定义的函数dateChange来实现这个功能。

#日期转换

def dateChange(dateSer):

dateList = []

for i in dateSer:

#例如2018-01-01 星期五,分割后为:2018-01-01

str = i.split(' ')[0]

dateList.append(str)

dateChangeSer = pd.Series(dateList)

return dateChangeSer

dateChangeSer = dateChange(salesDf['销售时间'])

dateChangeSer

0 2018-01-01

1 2018-01-02

2 2018-01-06

3 2018-01-11

4 2018-01-15

5 2018-01-20

6 2018-01-31

7 2018-02-17

8 2018-02-22

9 2018-02-24

10 2018-03-05

11 2018-03-05

12 2018-03-05

13 2018-03-07

14 2018-03-09

15 2018-03-15

16 2018-03-15

17 2018-03-15

18 2018-03-20

19 2018-03-22

20 2018-03-23

21 2018-03-24

22 2018-03-24

23 2018-03-28

24 2018-03-29

25 2018-04-05

26 2018-04-07

27 2018-04-13

28 2018-04-22

29 2018-05-01

...

6545 2018-04-05

6546 2018-04-05

6547 2018-04-09

6548 2018-04-10

6549 2018-04-10

6550 2018-04-10

6551 2018-04-12

6552 2018-04-13

6553 2018-04-13

6554 2018-04-14

6555 2018-04-15

6556 2018-04-15

6557 2018-04-15

6558 2018-04-15

6559 2018-04-16

6560 2018-04-17

6561 2018-04-18

6562 2018-04-21

6563 2018-04-22

6564 2018-04-24

6565 2018-04-25

6566 2018-04-25

6567 2018-04-25

6568 2018-04-26

6569 2018-04-26

6570 2018-04-27

6571 2018-04-27

6572 2018-04-27

6573 2018-04-27

6574 2018-04-28

Length: 6575, dtype: object

salesDf['销售时间'] = dateChangeSer

salesDf.head()

在做完转化后再观察一下有没有产生新的缺失值

salesDf['销售时间'].isnull().any()

False

salesDf.dtypes

销售时间 object

社保卡号 object

商品编码 object

商品名称 object

销售数量 float64

应收金额 float64

实收金额 float64

dtype: object

数据没有产生新的缺失,我们继续向下,把销售时间的数据类型转为日期型。

dateSer=pd.to_datetime(salesDf['销售时间'], format = '%Y-%m-%d', errors='coerce')

dateSer

0 2018-01-01

1 2018-01-02

2 2018-01-06

3 2018-01-11

4 2018-01-15

5 2018-01-20

6 2018-01-31

7 2018-02-17

8 2018-02-22

9 2018-02-24

10 2018-03-05

11 2018-03-05

12 2018-03-05

13 2018-03-07

14 2018-03-09

15 2018-03-15

16 2018-03-15

17 2018-03-15

18 2018-03-20

19 2018-03-22

20 2018-03-23

21 2018-03-24

22 2018-03-24

23 2018-03-28

24 2018-03-29

25 2018-04-05

26 2018-04-07

27 2018-04-13

28 2018-04-22

29 2018-05-01

...

6545 2018-04-05

6546 2018-04-05

6547 2018-04-09

6548 2018-04-10

6549 2018-04-10

6550 2018-04-10

6551 2018-04-12

6552 2018-04-13

6553 2018-04-13

6554 2018-04-14

6555 2018-04-15

6556 2018-04-15

6557 2018-04-15

6558 2018-04-15

6559 2018-04-16

6560 2018-04-17

6561 2018-04-18

6562 2018-04-21

6563 2018-04-22

6564 2018-04-24

6565 2018-04-25

6566 2018-04-25

6567 2018-04-25

6568 2018-04-26

6569 2018-04-26

6570 2018-04-27

6571 2018-04-27

6572 2018-04-27

6573 2018-04-27

6574 2018-04-28

Name: 销售时间, Length: 6575, dtype: datetime64[ns]

dateSer.isnull().any()

True

compareDf = pd.DataFrame(dateSer[dateSer.isnull()],salesDf[dateSer.isnull()]['销售时间'])

compareDf

查看了下数据,产生空值的原因是因为数据中出现了'2018-02-29'这样实际不存在的日期。在实际应用中,最好能向业务部门询问一下产生的原因,看下是不是因为日期推算不正确导致了这样原因的产生,需不需要将这样的数据进行一下必要的修正。这里就简单的把数据进行删除。

salesDf['销售时间'] = dateSer

salesDf.dtypes

销售时间 datetime64[ns]

社保卡号 object

商品编码 object

商品名称 object

销售数量 float64

应收金额 float64

实收金额 float64

dtype: object

salesDf.shape

(6575, 7)

salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any')

salesDf.shape

(6552, 7)

salesDf=salesDf.reset_index(drop=True)

5)数据排序

销售记录一般是以销售时间为顺序排列的,所以我们对数据进行一下排序

#按销售时间排序

salesDf = salesDf.sort_values(by='销售时间')

#再次更新一下序号

salesDf = salesDf.reset_index(drop = True)

6)异常值处理

在下面数据集的描述指标中可以看出,存在销售数量为负的数据,这明显是不合理的,我们把这部分数据也进行删除

salesDf.describe()

#删除异常值:通过条件判断筛选出数据

#查询条件

querySer=salesDf.loc[:,'销售数量']>0

#应用查询条件

print('删除异常值前:',salesDf.shape)

salesDf=salesDf.loc[querySer,:]

print('删除异常值后:',salesDf.shape)

删除异常值前: (6552, 7)

删除异常值后: (6509, 7)

数据清洗完了之后,我们终于可以来搭建我们的模型啦。当然如果在模型搭建过程中再次发现数据异常情况,我们还是要对数据进行进一步的清洗。

4.构建模型

1)业务指标1:月均消费次数=总消费次数 / 月份数

总消费次数:同一天内,同一个人发生的所有消费算作一次消费。这里我们根据列名(销售时间,社区卡号)结合,如果这两个列值同时相同,只保留1条,将重复的数据删除

月份数:数据已经按照销售时间进行排序,只需将最后的数据与第一条数据相减就可换算出月份数

#总消费次数计算

kpDf = salesDf.drop_duplicates(subset=['销售时间','社保卡号'])

total = kpDf.shape[0]

print('总消费次数为:',total)

总消费次数为: 5345

#月份数计算

startDay = salesDf.loc[0,'销售时间']

print('开始日期:',startDay)

endDay = salesDf.loc[salesDf.shape[0]-1,'销售时间']

print('结束日期:',endDay)

monthCount = (endDay - startDay).days//30

print('月份数:',monthCount)

开始日期: 2018-01-01 00:00:00

结束日期: 2018-07-18 00:00:00

月份数: 6

#业务指标1:月均消费次数=总消费次数 / 月份数

kpi1 = total / monthCount

print('业务指标1:月均消费次数=',kpi1)

业务指标1:月均消费次数= 890.8333333333334

2)指标2:月均消费金额 = 总消费金额 / 月份数

totalMoney = salesDf['实收金额'].sum()

kpi2 = totalMoney / monthCount

print('业务指标2:月平均消费金额=',kpi2)

业务指标2:月平均消费金额= 50672.494999999624

3)指标3:客单价=总消费金额 / 总消费次数

kpi3 = kpi2 / kpi1

print('业务指标3:客单价=',kpi3)

业务指标3:客单价= 56.8821272217021

4)指标4:消费趋势,画图:折线图

#在进行操作之前,先把数据复制到另一个数据框中,防止对之前清洗后的数据框造成影响

groupDf=salesDf

#第1步:重命名行名(index)为销售时间所在列的值

groupDf.index=groupDf['销售时间']

groupDf.head()

#第2步:分组

gb=groupDf.groupby(groupDf.index.month)

#第3步:应用函数,计算每个月的消费总额

mounthDf=gb.sum()

mounthDf

#解决图表中中文表示不正的问题

import matplotlib as mpl

mpl.rcParams['font.sans-serif'] = ['SimHei']

mpl.rcParams['font.serif'] = ['SimHei']

import seaborn as sns

sns.set_style("darkgrid",{"font.sans-serif":['simhei', 'Arial']})

import matplotlib.pyplot as plt

%matplotlib inline

#绘制销售数量图

plt.plot(mounthDf['销售数量'],color = 'b')

plt.title('销售趋势')

plt.xlabel('2018年月份')

plt.ylabel('销售数量')

#设置图片大小

fig = plt.figure(figsize=(10,6))

#应收金额图

plt.plot(mounthDf['应收金额'],color = 'r',label = '应收金额')

#实收金额图

plt.plot(mounthDf['实收金额'],color = 'b',label = '实收金额')

#图标位置

plt.legend(loc='lower left')

#大标题

plt.title('应收金额与实收金额')

#X坐标标签

plt.xlabel('2018年月份')

#Y坐标标签

plt.ylabel('金额')

从图中可以看出销售数量和销售金额的整个趋势是基本一致的,四月份为最高点,二月份为前期一个最低点,而且在四月份以后销售一直处于向下的趋势,在记录的日期中,七月份达到了历史最低水平。

总结:

在这个简单的模型分析做成中,通过自己的发现查找以及百度顺利解决了问题,这里做一个简单的总结。

1.如果是默认索引的话,在数据清洗中发生数据行数的变化时,应该要用reset_index函数及时把索引最新化,这样可以避免很多意料之外的错误。

2.数据量不是很大的情况下,对于缺失值,我们应该多观察,看看能不能进行转换成合理的值,比如像这个数据集中【2018-02-29】这样的数据很可能是业务员录入失误,可以通过了解实际情况后修改数据。

3.在画图时发现中文的标题,xy坐标标识无法正常显示,通过百度加了关于字体的设置后顺利地解决了问题。

python药店销售数据分析_药房销售情况分析(python篇)相关推荐

  1. 用python处理excel 数据分析_像Excel一样使用python进行数据分析(1)

    (虽然是转载,但是是我每块都测试过得,容易出问题的地方我会添加一些自己的经验,仅供参考) 摘要:本篇文章通过python与excel的功能对比介绍如何使用python通过函数式编程完成excel中的数 ...

  2. python实现气象数据分析_气象数据可视化——利用Python绘制温度平流

    ##数据来源:NCEP再分析数据 import matplotlib.pyplot as plt from mpl_toolkits.basemap import Basemap import num ...

  3. python 在险价值_家庭医疗保险花费分析 - Python

    Part 1 数据获取 从Kaggle上面下载的个人在医疗保险上花费的数据集,该数据集1338行,7个字段,大小56KB.Medical Cost Personal Datasets 字段: Age, ...

  4. python新手入门教程思路-Python新手入门教程_教你怎么用Python做数据分析

    Python新手入门教程_教你怎么用Python做数据分析 跟大家讲了这么多期的Python教程,有小伙伴在学Python新手教程的时候说学Python比较复杂的地方就是资料太多了,比较复杂.很多网上 ...

  5. python药店销售数据分析_解析医院药店销售数据,看看Python数据分析结果有什么惊人的发现|python基础教程|python入门|python教程...

    https://www.xin3721.com/eschool/pythonxin3721/ 前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时 ...

  6. python药店销售数据分析_解析医院药店销售数据,看看Python数据分析结果有什么惊人的发现...

    Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待 4999元包邮 去购买 > 前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业 ...

  7. python药店销售数据分析_药店经营数据分析案例

    关于 XX 药店 09 年 1~7 月经营数据简析 雪域飞花 受 XX 药店委托, 我们对企业 09 年 1`7 月的经营数据通过瑞商源数据分析系统进行了计 算分析,现将分析结果列示如下: 一.销售数 ...

  8. python医药数据分析_药品销售数据分析--python

    一.数据分析的目的 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括总结的过程. 本篇文章中,假设以朝阳医院2018年销售数据为例,目的是了 ...

  9. 重点客户销售数据分析python_药品销售数据分析--python

    一.数据分析的目的 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括总结的过程. 本篇文章中,假设以朝阳医院2018年销售数据为例,目的是了 ...

最新文章

  1. 美国国安局承包商被捕,被刑事指控盗窃机密
  2. unity 纹理压缩格式‘_[2018.1]Unity贴图压缩格式设置
  3. 软件项目开发计划书【申明:来源于网络】
  4. Script:GridControl Repository Health Check
  5. 蓝桥杯练习系统习题-算法训练2
  6. Android 优化电池使用时间——根据需要操作广播接收器
  7. mysql怎么定位错误信息_Mysql主从复制异常,定位具体的SQL
  8. VMware vSphere Replication 5.5 安装配置【展现虚拟化商业价值征文大赛】
  9. 中南大学计算机学院羽毛球赛,“羽你同行”交通院第六届师生羽毛球赛圆满举办...
  10. java_函数的重载
  11. Uniswap V3 24小时交易量达12.9亿美元
  12. 更改计算机复制快捷键,电脑上怎么把一句话设置快捷键,电脑快捷键复制一句话-...
  13. 快速中值滤波利用VC++和OpenCV调用其封装的动态链接库出现的错误和处理
  14. Samsung SSD Magician 4.1三星固态硬盘优化工具官方中文版
  15. python爬虫爬取淘宝美食_python爬虫爬取淘宝商品信息
  16. Docker容器实现跨宿主机通信
  17. 思科实验-生成树协议STP
  18. 618年中大促八大情景话术大全(赶紧收藏)
  19. BIOS实战之读写逻辑设备(SIO)
  20. Node.js 单页应用

热门文章

  1. Commvault逻辑架构及组件说明
  2. JQuery简单使用
  3. ST2Vec: Spatio-Temporal Trajectory Similarity Learning in Road Networks
  4. 关于二叉树、四叉树和八叉树
  5. sql server 索引阐述系列二 索引存储结构
  6. jQuery动态添加按钮,绑定点击事件失效
  7. 8、接口与面向接口编程
  8. 一次qps测试实践(续)
  9. Linux系统装进U盘里,制作随身携带的便捷系统
  10. 任泽平:谏言、真相与几句心里话