上游,是勇士劈风破浪的终点,下游,是懦夫一帆风顺的归宿。
本文是Python<数据分析>基础知识点的姊妹篇,以药店销售数据分析为例,带你一起走一遍数据分析5部曲。
鲸歌:Python<数据分析>基础知识点zhuanlan.zhihu.com
#导入pandas包
import pandas as pd
1.提出问题
从销售数据中分析出以下业务指标 1)月均消费次数 2)月均消费金额 3)客单价 4)消费趋势
2.理解数据
#读取Excel数据:统一先按照str读入,之后转换
fileNameStr='./朝阳医院2018年销售数据.xlsx'
xls=pd.ExcelFile(fileNameStr,dtype='object')
salesDf=xls.parse('Sheet1',dtype='object')
#打印前几行,查看数据基本信息
salesDf.head()
#了解数据有多少行和多少列
salesDf.shape
#查看各列的数据类型
salesDf.dtypes
3.数据清洗
#①选择子集(本例只有7列,不需要)
#subSalesDf=salesDf.loc[0:4,'购药时间':'销售数量']
#subSalesDf
#②列名重命名
#字典:旧命名和新命名对应关系
colNameDict={'购药时间':'销售时间'}
salesDf.rename(columns = colNameDict,inplace=True)
salesDf.head()
#③缺失数据处理:
print('删除缺失值前大小',salesDf.shape)
python缺失值有3种:
1)Python内置的None值
2)在pandas中,将缺失值表示为NA,表示不可用not available。
3)对于数值数据,pandas使用浮点值NaN(Not a Number)表示缺失数据。
后面出来数据,如果遇到错误:说什么float错误,那就是有缺失值,需要处理掉
所以,缺失值有3种:None,NA,NaN
#删除列(销售时间,社保卡号)中为空的行
#how='any'在给定的任何一列中有缺失值就删除
salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any')
print('删除缺失值后大小',salesDf.shape)
#④数据类型转换
#字符串转换为数值(浮点数)
salesDf['销售数量']= salesDf['销售数量'].astype('float')
salesDf['应收金额']=salesDf['应收金额'].astype('float')
salesDf['实收金额']=salesDf['实收金额'].astype('float')
print('转换后的数据类型:n',salesDf.dtypes)
#处理日期:字符串转换为数据类型
#示例引入:
testList = '2018-09-06 星期三'.split(' ')
testList
testList[0]
'''
定义函数:分割销售日期,获取销售日期
输入:timeColSer 销售时间这一列,是个Series数据类型
输出: 分割后的时间,返回也是个Series数据类型
'''
def splitSaletime(timeColSer):
timeList=[]
for value in timeColSer:
dateStr=value.split(' ')[0]
timeList.append(dateStr)
timeSer=pd.Series(timeList)
return timeSer
#获取“销售时间”这一列
timeSer=salesDf.loc[:,'销售时间']
#对字符串进行分割,获取销售日期
dateSer=splitSaletime(timeSer)
dateSer[0:3]
salesDf.loc[:,'销售时间']=dateSer
salesDf.head()
#字符串转换日期
#errors='coerce'
#format是你原始数据中日期的格式
salesDf.loc[:,'销售时间']=pd.to_datetime(salesDf.loc[:,'销售时间'],
format='%Y-%m-%d',
errors='coerce')
salesDf.dtypes
'''
转换日期过程中不符合日期格式的数值会被转换为空值None,
再次清洗缺失值,本例(销售时间,社保卡号)中为空的行
'''
salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any')
'''
by:按那几列排序
ascending = True 降序
ascending = False 升序
'''
#按销售日期进行升序排列
salesDf=salesDf.sort_values(by='销售时间',ascending=True)
print('排序后的数据集')
salesDf.head()
#由上述反馈结果,行的序号发生变动,需要重命名:index:排序后的列索引值是之前的行号,需要修改成从0到N按顺序的索引值
salesDf=salesDf.reset_index(drop=True)
salesDf.head()
#⑥通过描述统计,查看是否存在异常值
salesDf.describe()
#删除异常值:通过条件判断筛选出数据
#查询条件
querySer=salesDf.loc[:,'销售数量']>0
#应用查询条件
print('删除异常值前:',salesDf.shape)
salesDf=salesDf.loc[querySer,:]
print('删除异常值后:',salesDf.shape)
4.构建模型
业务指标1:月均消费次数=总消费次数/月份数
'''
总消费数的定义:同一天内,同一个人发生的所有消费算作一次消费
根据列名(销售时间,社保卡号),如果一致,就删除,保留唯一记录
'''
kpi1_Df=salesDf.drop_duplicates(
subset=['销售时间','社保卡号'])
totalI=kpi1_Df.shape[0]
#总消费次数有多少行
print('总消费次数=',totalI)
#排序
'''
计算月份数:时间范围
'''
#按销售时间升序排序
kpi1_Df=kpi1_Df.sort_values(by='销售时间',ascending=True)
#重命名行名(index)
kpi1_Df=kpi1_Df.reset_index(drop=True)
kpi1_Df.head()
#获取时间范围
#最小时间值
startTime=kpi1_Df.loc[0,'销售时间']
#最大时间值
endTime=kpi1_Df.loc[totalI-1,'销售时间']
#计算月份数
#天数
daysI=(endTime-startTime).days
#月份数:运算符“//”表示取整除
#返回商的整数部分
monthsI=daysI//30
print('月份数:',monthsI)
#业务指标1:月均消费次数=总消费次数/月份数
kpi1_I=totalI//monthsI
print('业务指标1:月均消费次数',kpi1_I)
业务指标2:月均消费金额=总消费金额/月份数
#总消费金额
totalMoneyF=salesDf.loc[:,'实收金额'].sum()
totalMoneyF
#月均消费金额
monthMoneyF=totalMoneyF / monthsI
print('业务指标2:月均消费金额=',monthMoneyF)
业务指标3:客单价=总消费金额/总消费次数
'''
totalMoneyF:总消费金额
totalI:总消费次数
'''
pct=totalMoneyF/totalI
print('客单价:',pct)
虽然案例并不复杂,构建的模型只是几个简单的指标,但是在一步步写代码的过程中,还是需要厘清每一个指标的组成。
最后一步数据可视化,本文没有涉及,后续到可视化部分会重点讲述!