第四关:pandas分析实际案例-药店销售数据分析

import pandas as pd
import numpy as np

#读取数据
filename='E:\sale.xlsx'
xls=pd.ExcelFile(filename,dtype="object")
salesdf=xls.parse('Sheet1',dtype='object')
#打印出前5行数据
print(salesdf.head())

#数据大小,多少行多少列,注意shape后面不添加括号
print(salesdf.shape)

#数据类型:dtypes.后面也是不添加括号
print(salesdf.dtypes)

#数据清洗

#1)更改数据列头名字
"""
inplace=True是数据框本身会改动
inplace=False数据框本身不会变,而会创建一个改动后的新的数据框,默认的是flase

"""
dictnamecol={"购药时间":"销售时间"}
salesdf.rename(columns=dictnamecol,inplace=True)
print(salesdf.head())

#2) 缺失值处理
print("缺失前的数据大小:",salesdf.shape)
salesdf=salesdf.dropna(subset=["销售时间",'社保卡号'],how="any")
print("删除缺失后的大小:",salesdf.shape)

"""
数据类型的转换:字符串转为日期
销售数量和金额:字符串转为浮点型,有利于下面的describe进行统计,否则describe就会无法对销售数量和金额进行统计
"""
salesdf.loc[:,"销售数量"]=salesdf.loc[:,'销售数量'].astype("float")
salesdf.loc[:,"应收金额"]=salesdf.loc[:,'应收金额'].astype("float")
salesdf.loc[:,"实收金额"]=salesdf.loc[:,'实收金额'].astype("float")

#数据类型的转换
#定义一个函数,将列表中的字符串时间数据分列开,取第一个年月日,
def splitsaletime(timecolser):
    timelist=[]
    for value in timecolser:
        datastr=value.split(" ")[0]
        timelist.append(datastr)
    timeser=pd.Series(timelist)
    return timeser

#将excel中的第一行销售时间提取出来,运用到函数里面,再将提取出来的字符串年月日赋值给销售时间
timeser=salesdf.loc[:,'销售时间']
dataser=splitsaletime(timeser)
salesdf.loc[:,'销售时间']=dataser


"""
数据类型的转换:字符串转为日期
"""
#errors='coerce' 如果原始数据不符合日期的格式,转换后的值为空值NaT
#format 是原数据中的日期格式
salesdf.loc[:,'销售时间']=pd.to_datetime(salesdf.loc[:,"销售时间"],format='%Y-%m-%d',errors="coerce")
print(salesdf.dtypes)
#以上是销售时间从重命名,分列,获取年月日,再将年月日赋值给销售时间

#转换日期过程中不符合日期格式的数值会被转换为空值,
#这里删除列(销售时间,社保卡号)中为空的行
salesdf=salesdf.dropna(subset=['销售时间','社保卡号'],how='any')
print(salesdf.head())


#数据排序
"""
by:按哪一列排序
ascending=True,按照降序排列
ascending=False 按照升序排列
"""
#按照销售日期进行升序排列

salesdf=salesdf.sort_values(by="销售时间",ascending=True)
print(salesdf.head())

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

salesdf=salesdf.reset_index(drop=True)
print(salesdf.head())

#异常值处理
print(salesdf.describe())
#发现存在的销售数量<0的异常值

#删除异常值:通过条件筛选出数据
#查询条件
queryser=salesdf.loc[:,"销售数量"]>0
#应用查询条件
print("删除异常值前:",salesdf.shape)
salesdf=salesdf.loc[queryser,:]#布尔运算,因为上面的查询条件得到的是行,所以根据布尔索引行对应相应的行。
print("删除异常值后:",salesdf.shape)



#构建模型
#指标1:月平均消费次数
"""
总消费次数:同一天,同一个人的所有消费都算作是一次消费
根据列名(销售时间,社区卡号),如果这两个列值同时相同,只保留第一个
将重复的数据删除
"""
kpil_df=salesdf.drop_duplicates(subset=["销售时间",'社保卡号'])

#总得消费次数:有多少行
total=kpil_df.shape[0]

print("总得消费次数:",total)

#月份数
starttime=kpil_df.loc[0,"销售时间"]
endtime=kpil_df.loc[total-1,'销售时间']
days=(endtime-starttime).days
month=days//30
print("月份数:",month)

#业务指标1:月平均消费次数=总次数/月数
kpi1=total/month
print("月平均消费次数:",kpi1)

#业务指标2:月平均消费额
#因为总得金额是包含同一时间和同一个社保卡号的,因此是不能用kpi_df,应该用去重之前的sale_df
totalmoney=salesdf.loc[:,"实收金额"].sum()
monthmoney=totalmoney/month
print("月平均消费额:",monthmoney)

#业务指标3:客单价
'''
总消费额/总次数
'''
pct=totalmoney/total
print("客单价:",pct)



答案如下:

             购药时间           社保卡号    商品编码     商品名称 销售数量  应收金额   实收金额
0  2018-01-01 星期五      001616528  236701  强力VC银翘片    6  82.8     69
1  2018-01-02 星期六      001616528  236701  清热解毒口服液    1    28  24.64
2  2018-01-06 星期三     0012602828  236701       感康    2  16.8     15
3  2018-01-11 星期一  0010070343428  236701    三九感冒灵    1    28     28
4  2018-01-15 星期五    00101554328  236701    三九感冒灵    8   224    208
(6578, 7)
购药时间    object
社保卡号    object
商品编码    object
商品名称    object
销售数量    object
应收金额    object
实收金额    object
dtype: object
             销售时间           社保卡号    商品编码     商品名称 销售数量  应收金额   实收金额
0  2018-01-01 星期五      001616528  236701  强力VC银翘片    6  82.8     69
1  2018-01-02 星期六      001616528  236701  清热解毒口服液    1    28  24.64
2  2018-01-06 星期三     0012602828  236701       感康    2  16.8     15
3  2018-01-11 星期一  0010070343428  236701    三九感冒灵    1    28     28
4  2018-01-15 星期五    00101554328  236701    三九感冒灵    8   224    208
缺失前的数据大小: (6578, 7)
删除缺失后的大小: (6575, 7)
销售时间    datetime64[ns]
社保卡号            object
商品编码            object
商品名称            object
销售数量            object
应收金额            object
实收金额            object
dtype: object
        销售时间           社保卡号    商品编码     商品名称 销售数量  应收金额   实收金额
0 2018-01-01      001616528  236701  强力VC银翘片    6  82.8     69
1 2018-01-02      001616528  236701  清热解毒口服液    1    28  24.64
2 2018-01-06     0012602828  236701       感康    2  16.8     15
3 2018-01-11  0010070343428  236701    三九感冒灵    1    28     28
4 2018-01-15    00101554328  236701    三九感冒灵    8   224    208
           销售时间           社保卡号    商品编码          商品名称 销售数量   应收金额  实收金额
0    2018-01-01      001616528  236701       强力VC银翘片    6   82.8    69
3436 2018-01-01     0010616728  865099    硝苯地平片(心痛定)    2    3.4     3
1190 2018-01-01  0010073966328  861409  非洛地平缓释片(波依定)    5  162.5   145
3859 2018-01-01  0010073966328  866634   硝苯地平控释片(欣然)    6    111  92.5
3888 2018-01-01  0010014289328  866851   缬沙坦分散片(易达乐)    1     26    23
        销售时间           社保卡号    商品编码          商品名称 销售数量   应收金额  实收金额
0 2018-01-01      001616528  236701       强力VC银翘片    6   82.8    69
1 2018-01-01     0010616728  865099    硝苯地平片(心痛定)    2    3.4     3
2 2018-01-01  0010073966328  861409  非洛地平缓释片(波依定)    5  162.5   145
3 2018-01-01  0010073966328  866634   硝苯地平控释片(欣然)    6    111  92.5
4 2018-01-01  0010014289328  866851   缬沙坦分散片(易达乐)    1     26    23
    销售数量         应收金额         实收金额
count  6549.000000  6549.000000  6549.000000
mean      2.384486    50.449076    46.284370
std       2.375227    87.696401    81.058426
min     -10.000000  -374.000000  -374.000000
25%       1.000000    14.000000    12.320000
50%       2.000000    28.000000    26.500000
75%       2.000000    59.600000    53.000000
max      50.000000  2950.000000  2650.000000
[6 rows x 7 columns]
删除异常值前: (6549, 7)
删除异常值后: (6506, 7)
总得消费次数: 5342
月份数: 5
月平均消费次数: 1068.4
月平均消费额: 60802.02199999957
客单价: 56.9094178210404


猜你喜欢

转载自blog.csdn.net/qq_42787271/article/details/82702610