前面已经分享过python的基础语法,以及数据分析领域最常用的两个包:Numpy和Pandas(戳下面的链接),下面将用一个实际案例:《朝阳医院2018年销售数据.xlsx》和大家分享一下数据分析的基本流程。赵小娟儿Lyric:【科学计算工具一】初识Numpy
赵小娟儿Lyric:【科学计算工具二】初识Pandas
在此之前,我们先来学习一下,数据分析的基本过程~~
一、明确问题
这里有一份朝阳医院2018年高血压药物的销售数据,我们需要得到以下三个指标:
月均消费次数,总消费次数/月份数,作为销售部门的重要指标值之一。(注意:同一个人同一天的消费只能视为一次消费)
月均消费金额,总消费金额/月份数,主要作为衡量部门收益的一个指标。
客单价,也就是平均交易金额,总消费金额/总消费次数。销售部门看看是否需要提高客单价来提高收益。
总结:这次的数据分析目的是查看销售部门这段时间的销售业绩如何,部门收益如何,是否需要通过提高客单价增加收益。
二、 理解数据
1、采集数据:
2、导入数据:数据存放在excel中
#导包
import numpy as np
import pandas as pd
salesDf = pd.read_excel(r'C:\Users\Juan\Desktop\朝阳医院2018年销售数据.xlsx', dtype = 'object')
#以object的类型读入数据,是为了防止某些数据读不进来,后面再根据需要更改数据类型。
'''
查看数据基本信息
'''
#打印出前5行,以确保数据运行正常
salesDf.head()
3、查看数据的基本信息,从整体上理解数据通过info() 函数
info()函数观察结果: (1)数据一共有6578个观测 (2)7个变量/特征(购药时间,社保卡号,商品编码,商品名称,销售数量,应收金额,实收金额) (3)每个特征值对应的观测值均有缺失值
三、数据清洗
1、选择子集有时候原始数据的特征值很多,只有一部分是我们需要的(比如网络上爬取下来的数据中的ip地址这个特征值对后续数据处理没有意义,舍弃),这时就需要选择数据的部分子集作为我们数据处理的对象。
本案例的所有的特征值都要使用到,不需要选择子集(代码展示一下如何截取子集,可用于其他案例)
2、列明重命名原始数据中有些列名不符合我们的日常使用习惯或者不方便数据分析,需要重命名
通过观察,我们发现购药时间是医院方面的说法,而对于销售人员来说,购药时间即为销售时间,所以这里我们对这列进行重命名,可以采用rename函数实现。
salesDf.rename(columns={'购药时间':'销售时间'},inplace =True)
salesDf.head()
'''inplace = False 默认值,不修改原始数据,返回新的数据改成True后,原始数据会被改变'''
3、缺失值处理原始数据有控制,不方便后续建模分析,需要进行一定的处理,可以删除或者补充其他数据
一开始查看数据信息的时候,就发现了每个特征值都有数据缺失现象。 缺失数据常用的处理方式为删除含有缺失数据的记录或者利用算法去补全缺失数据。这里因为数据样本较大,可以直接将缺失值删除。
'''
用df.dropna() 函数删除缺失值
'''
salesDf = salesDf.dropna(subset=['销售时间','社保卡号'],
how = 'any')
'''
参数subset,存放删除指定列的缺失值
参数how,传入any,表示只有任意一列有缺失值,就删除
删除前有6578条信息药店数据分析,删除后只有6575条信息,总共有3条数据是缺失被删除,所以这份数据还是比较完整的。
4、数据类型转换为方便计算,有时候需要把字符串类型的数据转换为数值型数据
因为一开始避免有些数据导出进来发生变化,所以统一以'object' 格式导入,所以根据需要进行数据类型转换。
# 数据类型转换
salesDf['销售数量'] = salesDf['销售数量'].astype('float')
salesDf['应收金额'] = salesDf['应收金额'].astype('float')
salesDf['实收金额'] = salesDf['实收金额'].astype('float')
salesDf.dtypes
再次观察销售时间这一列数据,前面是具体销售日期,后面是星期几。后面的星期几在数据分析过程中不需要用到,因此要把销售时间列中日期和星期使用split函数进行分割药店数据分析,分割后的时间,返回的是Series数据类型:
'''
处理思路:把销售时间这一列数据单独拿出来(Series数据类型),通过调用一个分割函数,
返回一个新的日期数据(Series数据类型),替换原来数据中的销售时间列。
'''
'''
定义函数:分割销售时间,获取销售日期
输入:timeColSer 销售时间列,是个Series数据类型
输出:分割后的日期,也是个Series数据类型
'''
def splitSaletime(timeColSer):
saledateList = [] # 定义一个列表容器,存放分割好的日期
for value in timeColSer:
saledateStr = value.split(' ')[0]
saledateList.append(saledateStr)
#将列表转化为Series数据类型
saledata = pd.Series(saledateList)
return saledata
dateSer = splitSaletime(salesDf['销售时间']) # 调用函数,将销售时间列作为参数传入
salesDf['销售时间'] = dateSer # 修改销售时间这一列的值
salesDf.head()
接着把切割后的日期转为时间格式,方便后面的数据统计:
'''
利用pandas的to_datetime 方法将日期转为时间格式
'''
salesDf.loc[:,'销售时间'] = pd.to_datetime(salesDf.loc[:,'销售时间'],
format = '%Y-%m-%d',
errors = 'coerce')
salesDf.dtypes
'''
format: 指原始数据中的日期格式
errors = 'coerce',如果原始数据不符合日期格式,转换后为NaT
'''
转换日期后,会有部分不符合格式要求的数据为NaT,
这里删除列(销售时间,社保卡号)中为空的行
'''
print('删除前数据:',salesDf.shape)
salesDf = salesDf.dropna(subset = ['销售时间','社保卡号'], how = 'any')
print('删除后数据:',salesDf.shape)
5、数据排序方便我们发现更多有价值的信息
一般原始数据中有时间这个特征值时,都会想到排个序,看看数据什么情况。
'''
此时时间是没有按顺序排列的,所以还是需要排序一下,
排序之后索引会被打乱,所以也需要重置一下索引。
用sort_values()数值进行排序,用sort_index()进行索引排序
by:表示按哪一列进行排序,ascending=True表示升序排列,ascending=False表示降序排列
'''
salesDf = salesDf.sort_values(by = '销售时间',ascending = True)
salesDf.head()
# 用sort_index() 将index重新排序
salesDf = salesDf.sort_index()
salesDf.head()
6、异常值处理过大或者过小的异常值,会影响整体的数据分析,需要进行处理
'''
查看数据的描述性统计信息
'''
salesDf.describe()
观察结果可知:销售数量,营收金额,实收金额最小值居然是个负数,显然不合常理,需要对这样的异常值进行删除。
# 删除异常值,通过条件判断筛选出数据
# 查询条件
querySer = salesDf.loc[:,'销售数量']>0
#应用查询条件
print('删除异常值前:',salesDf.shape)
salesDf = salesDf.loc[querySer,:]
print('删除异常值后:',salesDf.shape)
数据清洗结束
四、构建模型
三个指标:
月均消费次数,总消费次数/月份数,同一个人同一天的消费只能视为一次消费,也就是说,社保卡号和购药时间相同的,视为一次消费,需要删除重复项。
'''
来源【首席数据官】,更多内容/合作请关注「辉声辉语」公众号,送10G营销资料!
版权声明:本文内容来源互联网整理,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 jkhui22@126.com举报,一经查实,本站将立刻删除。