分享

数据分析的基本过程——Python:Numpy、Pandas

 东西二王 2019-05-17

在数据分析时,用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的数据类型

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

2、查询使用使用索引位置下标。

#查询,使用索引位置下标 ar[1] print('ar[1]输出结果:',ar[1])

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

查询的原理如下图:

数据分析的基本过程——Python:Numpy、Pandas

3、切片访问:获取指定序号范围的元素。

#切片访问:获取指定序号范围的元素
ar[1:3] #a[1:3]获取到的是序号从1到2的元素,他是一个左闭右开的区间
print('ar[1:3]输出结果:',ar[1:3])

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

切片访问的原理如下图:

数据分析的基本过程——Python:Numpy、Pandas

4、查看数据类型dtype。

#查看数据类型dtype ar.dtype print('查看ar的数据类型:',ar.dtype)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

5、统计计算。

print('ar内数据的平均值:',ar.mean()) #计算平均值
print('ar内数据的标准差:',ar.std ()) #计算标准差
print('ar内数据的方差:',ar.var()) #计算方差
print('ar内数据的最大值:',ar.max()) #计算最大值
print('ar内数据的最小值:',ar.min()) #计算最小值

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

6、向量化运行:乘以标量

ar_1 = ar*10 #ar内每个元素都乘以10 print('输出ar_1的结果是:',ar_1)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

2)、获取描述统计信息。

sm = stockS.describe() print('输出stockS数据的描述统计信息:\n',sm)

数据分析的基本过程——Python:Numpy、Pandas

3)、iloc属性用于根据索引获取值。

st0 = stockS.iloc[0] #按照整数的行位置进行索引
print('输出stockS行号为0的数据:',st0)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

4)、loc属性用于根据索引获取值。

st_tx = stockS.loc['腾讯'] #按照行名进行索引 print('输出stockS行名“腾讯”的数据:',st_tx)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

6)、处理缺失值:NaN

方法1:删除缺失值 s3_notna = s3.dropna() print('将s3删除缺失值后:\n',s3_notna)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

方法2:将缺失值进行填充

s3=s1.add(s2,fill_value=0)
print('s1与s2进行向量相加时,出现缺失值直接补0,得到s3为:\n',s3)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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,:])

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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))

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

2)、按每列或行来求值。

print('默认按列进行运算:\n',salesDf.mean()) print('--------------') print('axis=1时按行进行运算:\n',salesDf.mean(axis=1))

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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])

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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['商品名称'])

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

#通过列表来选择某几列的数据
salesDf[['商品名称','销售数量']]
#通过切片功能,获取指定范围的列
salesDf.loc[:,'购药时间':'销售数量']
print('查看商品名称、销售数量数据:\n',salesDf[['商品名称','销售数量']])
print('------------')
print('查看购药时间到销售数量各列数据:\n',salesDf.loc[:,'购药时间':'销售数量'])

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

5)、条件判断

#通过条件判断筛选 #第1步:构建查询条件 querySer=salesDf.loc[:,'销售数量']>1 #第1步:将查询条件写入 salesDf1 = salesDf.loc[querySer,:] print('销售数量大于1的数据:\n',salesDf1)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

6)、 查看数据集描述统计信息

#读取Ecxcel数据
import os
os.chdir(r'D:\data3')
fileNameStr='朝阳医院2018年销售数据.xlsx'
xls = pd.ExcelFile(fileNameStr)
salesDf = xls.parse('Sheet1')
#打印出前3行,以确保数据运行正常
salesDf.head(3)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

#有多少行,多少列 salesDf.shape

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

#查看某一列的数据类型
salesDf.loc[:,'销售数量'].dtype

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

#查看每一列的统计数值 c = salesDf.describe()

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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()

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

#有多少行,多少列
salesDf.shape

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

即数据有6578行,7列。

#查看每一列的数据类型 salesDf.dtypes

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

3.3、数据清洗

数据清洗有6个基本步骤:1、选择子集;2、列名重命名;3、缺失数据处理;4、数据类型转换;5、数据排序;6、异常值处理。这次使用的数据列数字段较少,不需要选择子集。

1)、 列名重命名

colNameDict = {'购药时间':'销售时间'} #字典:旧列名和新列名对应关系
salesDf.rename(columns = colNameDict,inplace=True) #在原表上将购药时间列名改为销售时间
salesDf.head()

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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() #查看处理的结果

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

将“销售时间”这一列的数据修改为处理好的“dateSer”数据。

salesDf.loc[:,'销售时间']=dateSer #修改销售时间这一列的值
salesDf.head() #查看处理的结果

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

因为“销售时间”这一列数据类型还是属于字符类型,需要转化为时间类型。

salesDf.loc[:,'销售时间']=pd.to_datetime(salesDf.loc[:,'销售时间'], format='%Y-%m-%d', errors='coerce') #errors='coerce' 如果原始数据不符合日期的格式,转换后的值为空值NaT #format 是你原始数据中日期的格式 salesDf.dtypes #查看处理后的数据类型

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

因为在“销售时间”转化为时间类型时,会有空值产生。还有“社保卡号”这一列也不能这空值,所以要将“销售时间”、“社保卡号”这一列出现空值的行删除。

salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any') #删除列(销售时间,社保卡号)中为空的行
salesDf.shape #查看处理后的数据行数与列数

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

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() #查看数据排序后的结果

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

5)、异常值处理

从数据上看,销售数量是关联到应收金额、实收金额,首先销售数量不能小于0,先简单查看数据的统计情况。

salesDf.describe() #查看每列的统计值

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

删除异常值:通过条件判断筛选出数据。

querySer=salesDf.loc[:,'销售数量']>0 #查询条件,生成一个大于0的布尔值数据列 print('删除异常值前:',salesDf.shape) salesDf=salesDf.loc[querySer,:] #应用查询条件 print('删除异常值后:',salesDf.shape) salesDf.describe() #查看每列的统计值

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

3.4、构建模型

1)、 月均消费次数=总消费次数 / 月份数;

其中对于消费次数的定义再细化:同一天内,同一个人发生的所有消费应该是算做一次消费。从数据的计算实现来操作,可以根据”销售时间“和”社区卡号“,两列值只取唯一值,也就是如果两值同时相同,就只保留1条,将重复的删除。

kpi1_Df=salesDf.drop_duplicates(subset=['销售时间', '社保卡号'])
totalI=kpi1_Df.shape[0] #获取行数,即是总消费次数
print('总消费次数=',totalI)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

月份数的计算,通过对销售时间排序,得到最小时间与最大时间,再用最大时间减最小时间并整除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() #相看结果

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

#第2步:获取时间范围
startTime=kpi1_Df.loc[0,'销售时间'] #最小时间值
endTime=kpi1_Df.loc[totalI-1,'销售时间'] #最大时间值
#第3步:计算月份数
daysI=(endTime-startTime).days #天数
monthsI=daysI//30 #月份数
print('月份数:',monthsI)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

#业务指标1:月均消费次数=总消费次数 / 月份数 kpi1_I=totalI // monthsI print('业务指标1:月均消费次数=',kpi1_I)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

2)、月均消费金额 = 总消费金额 / 月份数;

其中月份数计算出来,现在要计算的是总消费金额,只要对”实收金额“这一列相加就可以获得总消费金额。

totalMoneyF=salesDf.loc[:,'实收金额'].sum() #总消费金额
monthMoneyF=totalMoneyF / monthsI #月均消费金额
print('业务指标2:月均消费金额=%.2f'%(monthMoneyF))

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

3)、 客单价=总消费金额 / 总消费次数

其中总消费金额和总消费次数在前面的计算过程已有,直接调用就可以。即totalMoneyF是总消费金额,totalI是总消费次数。

pct=totalMoneyF / totalI #月均消费金额 print('客单价:%.2f'%pct)

生成结果:

数据分析的基本过程——Python:Numpy、Pandas

由此得到几点:

1、数据分析有一个基本的套路:1)、提出问题;2)、理解数据;3)、数据清洗;4)、构建模型;5)、数据可视化(待续)。

2、数据清洁的基本过程:1)、选择子集;2)、列名重命名;3)、缺失数据处理;4)、数据类型转换;5)、数据排序;6)、异常值处理。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多