在数据分析时,用Python进行数据处理主要使用的两个包:Numpy、Pandas。Numpy包是数值编程工具:N维数组对象:ndarray,对数组结构数据进行运算(不用遍历循环),有随机数、线性代数、傅里叶变换等功能。Pandas包是基于Numpy构建,为数据分析而存在,有一维数组Series 和二维数组 Dataframe,可直接读取数据并做处理(高效简单),兼容各种数据库并支持各种分析算法。数据处理主要有一维的行或列,还有二维的行和列(类似EXCEL),Numpy和Pandas也有一维、二维数据,并且在Numpy的基础上的Pandas的一维数组Series 和二维数组 Dataframe可以更高效处理数据。主要将从一维数据开始,然后再到二维数据,再以一个数据分析的案例来学习数据分析的基本过程。 import numpy as np #导入numpy包
import pandas as pd #导入pandas包
已设置了Numpy、Pandas简称,后续以np、pd表示
1、一维数据分析 1.1、一维数据分析:Numpy 1)、一维数组array的定义,可以使用到numpy.array()函数去设置。 #定义:一维数组array,参数传入的是一个列表[2,3,4,5,6,8,9] ar = np.array([2,3,4,5,6,8,9]) print('输出数组ar:',ar) #输出数组ar print('数组ar的数据类型:',type(ar)) #数组ar的数据类型 生成结果: 2、查询使用使用索引位置下标。 #查询,使用索引位置下标
ar[1]
print('ar[1]输出结果:',ar[1])
生成结果: 查询的原理如下图: 3、切片访问:获取指定序号范围的元素。 #切片访问:获取指定序号范围的元素 ar[1:3] #a[1:3]获取到的是序号从1到2的元素,他是一个左闭右开的区间 print('ar[1:3]输出结果:',ar[1:3]) 生成结果: 切片访问的原理如下图: 4、查看数据类型dtype。 #查看数据类型dtype
ar.dtype
print('查看ar的数据类型:',ar.dtype)
生成结果: 5、统计计算。 print('ar内数据的平均值:',ar.mean()) #计算平均值 print('ar内数据的标准差:',ar.std ()) #计算标准差 print('ar内数据的方差:',ar.var()) #计算方差 print('ar内数据的最大值:',ar.max()) #计算最大值 print('ar内数据的最小值:',ar.min()) #计算最小值 生成结果: 6、向量化运行:乘以标量 ar_1 = ar*10 #ar内每个元素都乘以10
print('输出ar_1的结果是:',ar_1)
生成结果: 1.2、一维数据分析:Pandas 1)、定义:Pandas一维数据结构:Series。 stockS=pd.Series([54.74,190.9,173.14,1050.3,181.86,1139.49], index=['腾讯', '阿里巴巴', '苹果', '谷歌', 'Facebook', '亚马逊']) #创建Series print(stockS) 生成结果: 2)、获取描述统计信息。 sm = stockS.describe()
print('输出stockS数据的描述统计信息:\n',sm)
3)、iloc属性用于根据索引获取值。 st0 = stockS.iloc[0] #按照整数的行位置进行索引 print('输出stockS行号为0的数据:',st0) 生成结果: 4)、loc属性用于根据索引获取值。 st_tx = stockS.loc['腾讯'] #按照行名进行索引
print('输出stockS行名“腾讯”的数据:',st_tx)
生成结果: 5)、向量化运算:向量相加(根据标签自动对齐,)。 s1=pd.Series([1,2,3,4],index=['a','b','c','d']) s2=pd.Series([10,20,30,40],index=['a','b','e','f']) s3=s1 s2 #根据标签自动对齐,空值和任何值计算结果扔为空值 print('输出s3的结果:\n',s3) 生成结果: 6)、处理缺失值:NaN 方法1:删除缺失值
s3_notna = s3.dropna()
print('将s3删除缺失值后:\n',s3_notna)
生成结果: 方法2:将缺失值进行填充 s3=s1.add(s2,fill_value=0) print('s1与s2进行向量相加时,出现缺失值直接补0,得到s3为:\n',s3) 生成结果: 2、二维数据分析 2.1、二维数据分析:Numpy 1)、二维数组array的定义,可以使用到numpy.array()函数去设置。 #定义二维数组
ar=np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]])
print('输出数组ar:\n',ar) #输出数组ar
生成结果: 2)、索引与切片 #获取行号是0,列号是2的元素a[0,2] ar[0,2] #获取第1行 ar[:,0] #获取第1列 ar[0,:] print('输出ar[0,2]:',ar[0,2]) print('获取第1行:',ar[:,0]) print('获取第1列:',ar[0,:]) 生成结果: 3)、Numpy数轴参数:axis,axis=0是列方向,axis=1是行方向。 #如果没有指定数轴参数,会计算整个数组的平均值
print('ar内所有数求平均:',ar.mean())
#按轴计算:axis=0计算每一列
print('ar内每一列数求平均:',ar.mean(axis = 0))
#按轴计算:axis=1计算每一行
print('ar内每一行数求平均:',ar.mean(axis = 1))
生成结果: 2.2、Pandas二维数组:数据框(DataFrame) 1)、二维数组DataFrame的定义。 #第1步:定义一个有序的元组 salesDict=( ('购药时间',['2018-01-01 星期五','2018-01-02 星期六','2018-01-06 星期三']), ('社保卡号',['001616528','001616528','0012602828']), ('商品编码',[236701,236701,236701]), ('商品名称',['强力VC银翘片','清热解毒口服液','感康']), ('销售数量',[6,1,2]), ('应收金额',[82.8,28,16.8]), ('实收金额',[69,24.64,15])) #导入有序字典 from collections import OrderedDict #定义一个有序字典 salesOrderDict=OrderedDict(salesDict) #定义数据框:传入字典,列名 salesDf=pd.DataFrame(salesOrderDict) salesDf 生成结果: 2)、按每列或行来求值。 print('默认按列进行运算:\n',salesDf.mean())
print('--------------')
print('axis=1时按行进行运算:\n',salesDf.mean(axis=1))
生成结果: 3)、 查询数据:iloc属性用于根据位置获取值 #查询第1行第2列的元素 salesDf.iloc[0,1] #获取第1行,:代表所有列 salesDf.iloc[0,:] #生成一个Series #获取第1列,:代表所有行 salesDf.iloc[:,0] #生成一个Series print('查询第1行第2列的元素:',salesDf.iloc[0,1]) print('---------') print('获取第1行:\n',salesDf.iloc[0,:]) print('---------') print('获取第1列:\n',salesDf.iloc[:,0]) 生成结果: 4)、 查询数据:loc属性用于根据索引获取值。 #查询第1行第1列的元素
salesDf.loc[0,'商品编码']
#获取第1行
salesDf.loc[0,:]
#简单方法:获取“商品名称”这一列
salesDf['商品名称']
print('第1行第1列的元素:',salesDf.loc[0,'商品编码'])
print('--------------')
print('获取第1行:\n',salesDf.loc[0,:])
print('--------------')
print('简单方法:获取“商品名称”这一列\n',salesDf['商品名称'])
生成结果: #通过列表来选择某几列的数据 salesDf[['商品名称','销售数量']] #通过切片功能,获取指定范围的列 salesDf.loc[:,'购药时间':'销售数量'] print('查看商品名称、销售数量数据:\n',salesDf[['商品名称','销售数量']]) print('------------') print('查看购药时间到销售数量各列数据:\n',salesDf.loc[:,'购药时间':'销售数量']) 生成结果: 5)、条件判断 #通过条件判断筛选
#第1步:构建查询条件
querySer=salesDf.loc[:,'销售数量']>1
#第1步:将查询条件写入
salesDf1 = salesDf.loc[querySer,:]
print('销售数量大于1的数据:\n',salesDf1)
生成结果: 6)、 查看数据集描述统计信息 #读取Ecxcel数据 import os os.chdir(r'D:\data3') fileNameStr='朝阳医院2018年销售数据.xlsx' xls = pd.ExcelFile(fileNameStr) salesDf = xls.parse('Sheet1') #打印出前3行,以确保数据运行正常 salesDf.head(3) 生成结果: #有多少行,多少列
salesDf.shape
生成结果: #查看某一列的数据类型 salesDf.loc[:,'销售数量'].dtype 生成结果: #查看每一列的统计数值
c = salesDf.describe()
生成结果: 3、案例:药店销售数据分析 数据分析的基本过程:1、 提出问题→2、理解数据→3、数据清洗→4、构建模型→5、数据可视化。 3.1、提出问题 可以从销售数据中分析出业务指标: 1)、月均消费次数; 2)、月均消费金额; 3)、客单价; 3.2、理解数据 1)、读取销售数据 import pandas as pd fileNameStr='D:/data3/朝阳医院2018年销售数据.xlsx' xls = pd.ExcelFile(fileNameStr) salesDf = xls.parse('Sheet1') 2)、查看数据基本信息 #打印出前5行,以确保数据运行正常
salesDf.head()
生成结果: #有多少行,多少列 salesDf.shape 生成结果: 即数据有6578行,7列。 #查看每一列的数据类型
salesDf.dtypes
生成结果: 3.3、数据清洗 数据清洗有6个基本步骤:1、选择子集;2、列名重命名;3、缺失数据处理;4、数据类型转换;5、数据排序;6、异常值处理。这次使用的数据列数字段较少,不需要选择子集。 1)、 列名重命名 colNameDict = {'购药时间':'销售时间'} #字典:旧列名和新列名对应关系 salesDf.rename(columns = colNameDict,inplace=True) #在原表上将购药时间列名改为销售时间 salesDf.head() 生成结果: 2)、 缺失数据处理 python缺失值有3种:1、Python内置的None值;2、在pandas中,将缺失值表示为NA,表示不可用not available;3、对于数值数据,pandas使用浮点值NaN(Not a Number)表示缺失数据。 #删除列(销售时间,社保卡号)中为空的行
salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any')#how='any' 在给定的任何一列中有缺失值就删除
print('删除缺失后大小',salesDf.shape)
生成结果: 3)、数据类型转换 从数据上看,销售时间是一个文本形式的数据,需要将数据转换为日期数据类型。销售时间一列的数据 是以空格分开一个标准日期和一个星期几的格式,需要编写一个函数,分割销售日期的前一分部,获取销售日期。 def splitSaletime(timeColSer): timeList=[] #自建一个空列表,将处理完的数据存入 for value in timeColSer: dateStr=value.split(' ')[0] #例如2018-01-01 星期五,分割后为:2018-01-01 timeList.append(dateStr) #将分割后的日期格式存入空列表 timeSer=pd.Series(timeList) #将列表转行为一维数据Series类型 return timeSer 使用定义好的splitSaletime函数处理“销售时间”这一列的数据。 timeSer=salesDf.loc[:,'销售时间'] #获取“销售时间”这一列
dateSer=splitSaletime(timeSer) #对字符串进行分割,获取销售日期
dateSer.head() #查看处理的结果
生成结果: 将“销售时间”这一列的数据修改为处理好的“dateSer”数据。 salesDf.loc[:,'销售时间']=dateSer #修改销售时间这一列的值 salesDf.head() #查看处理的结果 生成结果: 因为“销售时间”这一列数据类型还是属于字符类型,需要转化为时间类型。 salesDf.loc[:,'销售时间']=pd.to_datetime(salesDf.loc[:,'销售时间'],
format='%Y-%m-%d',
errors='coerce')
#errors='coerce' 如果原始数据不符合日期的格式,转换后的值为空值NaT
#format 是你原始数据中日期的格式
salesDf.dtypes #查看处理后的数据类型
生成结果: 因为在“销售时间”转化为时间类型时,会有空值产生。还有“社保卡号”这一列也不能这空值,所以要将“销售时间”、“社保卡号”这一列出现空值的行删除。 salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any') #删除列(销售时间,社保卡号)中为空的行 salesDf.shape #查看处理后的数据行数与列数 生成结果: 4)、 数据排序 从数据上看,以时间为维度可以对“销售时间”排序,并且排序后由于行名会有变化,所以重名行名(index). salesDf=salesDf.sort_values(by='销售时间',ascending=True,na_position='first')
#by:按哪几列排序
#ascending=True 表示升序排列
#ascending=False表示降序排列
#na_position=True表示排序的时候,把空值放到前列
salesDf=salesDf.reset_index(drop=True)
print('排序后并修改行名的数据集')
salesDf.head() #查看数据排序后的结果
生成结果: 5)、异常值处理 从数据上看,销售数量是关联到应收金额、实收金额,首先销售数量不能小于0,先简单查看数据的统计情况。 salesDf.describe() #查看每列的统计值 生成结果: 删除异常值:通过条件判断筛选出数据。 querySer=salesDf.loc[:,'销售数量']>0 #查询条件,生成一个大于0的布尔值数据列
print('删除异常值前:',salesDf.shape)
salesDf=salesDf.loc[querySer,:] #应用查询条件
print('删除异常值后:',salesDf.shape)
salesDf.describe() #查看每列的统计值
生成结果: 3.4、构建模型 1)、 月均消费次数=总消费次数 / 月份数; 其中对于消费次数的定义再细化:同一天内,同一个人发生的所有消费应该是算做一次消费。从数据的计算实现来操作,可以根据”销售时间“和”社区卡号“,两列值只取唯一值,也就是如果两值同时相同,就只保留1条,将重复的删除。 kpi1_Df=salesDf.drop_duplicates(subset=['销售时间', '社保卡号']) totalI=kpi1_Df.shape[0] #获取行数,即是总消费次数 print('总消费次数=',totalI) 生成结果: 月份数的计算,通过对销售时间排序,得到最小时间与最大时间,再用最大时间减最小时间并整除30(简化计算),最终得到月份数。 #第1步:按销售时间升序排序
kpi1_Df=kpi1_Df.sort_values(by='销售时间',
ascending=True)
#重命名行名(index)
kpi1_Df=kpi1_Df.reset_index(drop=True)
kpi1_Df.head()
kpi1_Df.tail() #相看结果
生成结果: #第2步:获取时间范围 startTime=kpi1_Df.loc[0,'销售时间'] #最小时间值 endTime=kpi1_Df.loc[totalI-1,'销售时间'] #最大时间值 #第3步:计算月份数 daysI=(endTime-startTime).days #天数 monthsI=daysI//30 #月份数 print('月份数:',monthsI) 生成结果: #业务指标1:月均消费次数=总消费次数 / 月份数
kpi1_I=totalI // monthsI
print('业务指标1:月均消费次数=',kpi1_I)
生成结果: 2)、月均消费金额 = 总消费金额 / 月份数; 其中月份数计算出来,现在要计算的是总消费金额,只要对”实收金额“这一列相加就可以获得总消费金额。 totalMoneyF=salesDf.loc[:,'实收金额'].sum() #总消费金额 monthMoneyF=totalMoneyF / monthsI #月均消费金额 print('业务指标2:月均消费金额=%.2f'%(monthMoneyF)) 生成结果: 3)、 客单价=总消费金额 / 总消费次数 其中总消费金额和总消费次数在前面的计算过程已有,直接调用就可以。即totalMoneyF是总消费金额,totalI是总消费次数。 pct=totalMoneyF / totalI #月均消费金额
print('客单价:%.2f'%pct)
生成结果: 由此得到几点: 1、数据分析有一个基本的套路:1)、提出问题;2)、理解数据;3)、数据清洗;4)、构建模型;5)、数据可视化(待续)。 2、数据清洁的基本过程:1)、选择子集;2)、列名重命名;3)、缺失数据处理;4)、数据类型转换;5)、数据排序;6)、异常值处理。 |
|