pandas是python中基于NumPy的数据分析科学包,有着很强大的功能。学习使用好pandas包,对数据分析有着很大的帮助。
首先认识了解NumPy,再联系起来学习pandas。NumPy中的关键就是数组array,包括一维和多维。相似的pandas中也有Series和DataFrame。常用的功能包括文件的读取,行列索引的更改,数据类型的转换,切片和索引的使用,缺失值异常值的处理,基本的统计方法,时间日期的处理,数据的排序等。
以下案例使用了一些pandas的常用功能。某医院小品销售数据分析。
Step1:
业务指标1:月均消费次数;业务指标2:月均消费金额;业务指标3:客单价;业务指标4:每月销售额。
Step2:
import pandas as pd
C:\Users\CEC\Desktop\第3关,pandas练习
fileNameStr=r'C:\Users\Administrator\Desktop\第3关,pandas练习/朝阳医院2018年销售数据.xlsx'
xls = pd.ExcelFile(fileNameStr, dtype='object')
salesDf = xls.parse('Sheet1',dtype='object')
#c查看数据基本信息
salesDf.head()
购药时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额
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
salesDf.shape
(6578, 7)
salesDf.dtypes
购药时间 object
社保卡号 object
商品编码 object
商品名称 object
销售数量 object
应收金额 object
实收金额 object
dtype: object
Step3:
#列的重命名
salesDf.rename(columns = {'购药时间':'销售时间'},inplace=True)
salesDf.head()
销售时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额
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
#删除列(销售时间,社保卡号)中为空的行
#how='any' 在给定的任何一列中有缺失值就删除
salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any')
print('删除缺失后大小',salesDf.shape)
删除缺失后大小 (6575, 7)
#字符串转换为数值(浮点型)
salesDf['销售数量'] = salesDf['销售数量'].astype('int')
salesDf['应收金额'] = salesDf['应收金额'].astype('float')
salesDf['实收金额'] = salesDf['实收金额'].astype('float')
print('转换后的数据类型:\n',salesDf.dtypes)
转换后的数据类型:
销售时间 object
社保卡号 object
商品编码 object
商品名称 object
销售数量 int32
应收金额 float64
实收金额 float64
dtype: object
time_date=salesDf['销售时间']
time_date.head()
0 2018-01-01 星期五
1 2018-01-02 星期六
2 2018-01-06 星期三
3 2018-01-11 星期一
4 2018-01-15 星期五
Name: 销售时间, dtype: object
#定义函数分割字符串
date2=[x.split(' ') for x in time_date]
date3=pd.Series([x[0] for x in date2])
date3.head()
0 2018-01-01
1 2018-01-02
2 2018-01-06
3 2018-01-11
4 2018-01-15
dtype: object
#定义函数分割字符串
''''def split_time(sale_time):
time_list=[]
for value in sale_time:
date_time=value.split(" ")[0]
time_list.append(date_time)
sale_date=pd.Series(time_list)
return sale_date
'''
'\'def split_time(sale_time):\n time_list=[]\n for value in sale_time:\n date_time=value.split(" ")[0]\n time_list.append(date_time)\n sale_date=pd.Series(time_list)\n return sale_date\n'
'''timeSer=salesDf.loc[:,'销售时间']
dateSer=split_time(timeSer)
dateSer.head()
'''
"timeSer=salesDf.loc[:,'销售时间']\ndateSer=split_time(timeSer)\ndateSer.head()\n"
#修改销售时间这一列的值
salesDf.loc[:,'销售时间']=date3
salesDf.head()
销售时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额
0 2018-01-01 001616528 236701 强力VC银翘片 6 82.8 69.00
1 2018-01-02 001616528 236701 清热解毒口服液 1 28.0 24.64
2 2018-01-06 0012602828 236701 感康 2 16.8 15.00
3 2018-01-11 0010070343428 236701 三九感冒灵 1 28.0 28.00
4 2018-01-15 00101554328 236701 三九感冒灵 8 224.0 208.00
#字符串转换为日期
salesDf.loc[:,'销售时间']=pd.to_datetime(salesDf.loc[:,'销售时间'],
format='%Y-%m-%d',
errors='coerce')
salesDf.dtypes
销售时间 datetime64[ns]
社保卡号 object
商品编码 object
商品名称 object
销售数量 int32
应收金额 float64
实收金额 float64
dtype: object
#获取销售时间列
sale_time=salesDf.loc[:,'销售时间']
sale_time[:5]
0 2018-01-01
1 2018-01-02
2 2018-01-06
3 2018-01-11
4 2018-01-15
Name: 销售时间, dtype: datetime64[ns]
'''
转换日期过程中不符合日期格式的数值会被转换为空值,
这里删除列(销售时间,社保卡号)中为空的行
'''
salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any')
salesDf.shape
(6549, 7)
#按销售日期进行升序排列
salesDf=salesDf.sort_values(by='销售时间',
ascending=True,
na_position='first')
print('排序后的数据集')
salesDf.head(3)
排序后的数据集
销售时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额
0 2018-01-01 001616528 236701 强力VC银翘片 6 82.8 69.0
3436 2018-01-01 0010616728 865099 硝苯地平片(心痛定) 2 3.4 3.0
1190 2018-01-01 0010073966328 861409 非洛地平缓释片(波依定) 5 162.5 145.0
#重命名行名(index):排序后的列索引值是之前的行号,需要修改成从0到N按顺序的索引值
salesDf=salesDf.reset_index(drop=True)# drop=True 删除原索引
salesDf.head()
销售时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额
0 2018-01-01 001616528 236701 强力VC银翘片 6 82.8 69.0
1 2018-01-01 0010616728 865099 硝苯地平片(心痛定) 2 3.4 3.0
2 2018-01-01 0010073966328 861409 非洛地平缓释片(波依定) 5 162.5 145.0
3 2018-01-01 0010073966328 866634 硝苯地平控释片(欣然) 6 111.0 92.5
4 2018-01-01 0010014289328 866851 缬沙坦分散片(易达乐) 1 26.0 23.0
#描述指标:查看出“销售数量”值不能小于0
salesDf.describe()
销售数量 应收金额 实收金额
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
#删除异常值:通过条件判断筛选出数据
#查询条件
querySer=salesDf.loc[:,'销售数量']>0
#应用查询条件
print('删除异常值前:',salesDf.shape)
salesDf=salesDf.loc[querySer,:]
print('删除异常值后:',salesDf.shape)
删除异常值前: (6549, 7)
删除异常值后: (6506, 7)
#删除重复数据
kpil_Df=salesDf.drop_duplicates(subset=['销售时间','社保卡号'])
total=kpil_Df.shape[0]
print("总消费次数:",total)
总消费次数: 5342
#按销售时间升序排序
kpil_Df=kpil_Df.sort_values(by='销售时间',ascending=True)
#重命名行名
kpil_Df=kpil_Df.reset_index(drop=True)
#最早时间
start_time=kpil_Df.loc[0,'销售时间']
#最晚时间
end_time=kpil_Df.loc[total-1,'销售时间']
#计算月份数
#天数
days=(end_time-start_time).days
days
months=days//30
print('月份数:',months)
月份数: 6
Step4:
4#业务指标1:月均消费次数
kpi_1=total//months
print('业务指标1:月均消费次数=',kpi_1)
#业务指标1:月均消费次数
kpi_1=total//months
print('业务指标1:月均消费次数=',kpi_1)
业务指标1:月均消费次数= 890
#业务指标2:月均消费金额
#总消费金额
total_money=salesDf['实收金额'].sum()
#月均消费金额
month_money=total_money/months
print('业务指标2:月均消费金额%s'%month_money)
业务指标2:月均消费金额50668.35166666666
#业务指标3: 客单价
pct=total_money/total
print('业务指标3,客单价:%s'%pct)
业务指标3,客单价:56.909417821040805
salesDf.loc[:,'实收金额'].plot()
<matplotlib.axes._subplots.AxesSubplot at 0x8cb0e80>
业务指标4:每月销售额
#增加销售月份列
date4=[x.split('-') for x in date3]
date5=pd.Series([x[0]+x[1] for x in date4])
date5.head()
salesDf['销售月份']=date5
salesDf.head()
销售时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额 销售月份
0 2018-01-01 001616528 236701 强力VC银翘片 6 82.8 69.0 201801
1 2018-01-01 0010616728 865099 硝苯地平片(心痛定) 2 3.4 3.0 201801
2 2018-01-01 0010073966328 861409 非洛地平缓释片(波依定) 5 162.5 145.0 201801
3 2018-01-01 0010073966328 866634 硝苯地平控释片(欣然) 6 111.0 92.5 201801
4 2018-01-01 0010014289328 866851 缬沙坦分散片(易达乐) 1 26.0 23.0 201801
month_sales=salesDf.groupby([salesDf['销售月份']]).sum()
month_sales
销售数量 应收金额 实收金额
销售月份
201801 2471 53879.1 49005.71
201802 1819 37196.7 34311.17
201803 2511 53360.3 48771.80
201804 2969 61946.2 56744.33
201805 2233 47514.5 43916.80
201806 2167 44931.3 41319.70
201807 1481 32508.8 29940.60
sales_pivot=pd.pivot_table(salesDf,index='销售月份',values=['销售数量','实收金额'],aggfunc=sum,margins=True)
sales_pivot
实收金额 销售数量
销售月份
201801 49005.71 2471
201802 34311.17 1819
201803 48771.80 2511
201804 56744.33 2969
201805 43916.80 2233
201806 41319.70 2167
201807 29940.60 1481
All 304010.11 15651
Step5:
这里我使用了pandas内置的可视化函数,方法与matplotlib类似。
barh1=month_sales['销售数量'].plot(kind='barh',figsize=(6,6))
barh1.legend(["sale_quantity"])
bar2=month_sales[['应收金额','实收金额']].plot(kind='bar',figsize=(6,6))
bar2.legend(["Receivable amount","Paid amount"])
每月销售量
每月应收金额和实收金额