数据分析基础知识——Python

前言:本文介绍了Python的一维数组分析和二维数组分析的相关基础知识点,以及简单地介绍了一个销售案例的数据分析。

1、一维数组分析

#导入numpy包
import numpy as np 
#导入pandas包
import pandas as pd
  • Numpy一维数组
#定义:一维数组array
a=np.array([2,3,4,5])

#1)查询元素
a[0]
2

#2)切片访问
a[1:3]
array([3, 4])

#3)循环访问
for i in a:
    print(i)
2
3
4
5

#4)数据类型
#dtype详细信息参考网址:https://docs.scipy.org/doc/numpy-1.10.1/reference/arrays.dtypes.html
a.dtype
dtype('int32')
  • Numpy一维数组与列表的区别
#一维数组的值只能为同种类型的数据
#1、统计功能:平均值mean()和标准差std()
a.mean()
3.5
a.std()
1.118033988749895

#2.向量化计算
#1)向量相加
a+a
array([ 4,  6,  8, 10])

#2)乘以标量
a*4
array([ 8, 12, 16, 20])

#3)乘以向量
a*a
array([ 4,  9, 16, 25])
  • Pandas一维数据结构
stockS=pd.Series([54,190.9,173.14,1050.3,181.86,1139.49],
index=['腾讯','阿里巴巴','苹果','谷歌','Facebook','亚马逊'])

#描述统计信息
stockS
腾讯            54.00
阿里巴巴         190.90
苹果           173.14
谷歌          1050.30
Facebook     181.86
亚马逊         1139.49
dtype: float64
stockS.describe()
count       6.000000
mean      464.948333
std       491.307473
min        54.000000
25%       175.320000
50%       186.380000
75%       835.450000
max      1139.490000
dtype: float64

#iloc属性用于根据位置获取值
stockS.iloc[0]
54.0

#loc属性根据索引获取值
stockS.loc['腾讯']
54.0
  • 向量相加
#向量化运算:向量相加
s1=pd.Series([1,2,3,4],index=['a','b','c','d'])
s2=pd.Series([5,6,7,8],index=['a','b','e','f'])
s3=s1+s2
s3
a    6.0
b    8.0
c    NaN
d    NaN
e    NaN
f    NaN
dtype: float64

#方法1:删除缺失值
s3.dropna()
a    6.0
b    8.0
dtype: float64

#方法2:将缺失值填充
s3=s1.add(s2,fill_value=1)#fill_value代表填充值为1
s3
a    6.0
b    8.0
c    4.0
d    5.0
e    8.0
f    9.0
dtype: float64

2、二维数据分析

  • Numpy二维数据结构
#定义二维数组
a=np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

#1)查询元素
a[0,2]
3

#2)获取第一行
a[0,:]
array([1, 2, 3, 4])

#3)获取第一列
a[:,0]
array([1, 5, 9])
  • Numpy数轴参数
#按所有行所有列来计算
a.mean()
6.5

#按轴计算,axis=1计算每一行,axis=0计算每一列
a.mean(axis=1)
array([ 2.5,  6.5, 10.5])
a.mean(axis=0)
array([5., 6., 7., 8.])
  • Pandas数据框(DataFrame)

Pandas二维数组相对于Numpy有两个优点:

1、Pandas数据框中每一列可以是不同的类型,方便表示Excel里的数据。

2、有类似Pandas一维数组里Series索引的功能,每行每列都有其索引值,有利于存储表格数据。#Numpy二维数组array没有iloc和loc功能

#第一步:定义一个字典,映射列名与对应列的值
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]
}

#第二步:定义数据框,参数传入字典
salesDf=pd.DataFrame(salesDict)
salesDf
购药时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额     
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
    
#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(salesDf)
#第四步:定义数据框:传入字典,列名
salesDf=pd.DataFrame(salesOrderDict)
salesDf
购药时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额     
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  
  
#2.平均值计算
#是按每列来求平均值
salesDf.mean()#相当于salesDf.mean(axis=0)
商品编码    236701.000000
销售数量         3.000000
应收金额        42.533333
实收金额        36.213333
dtype: float64

salesDf.mean(axis=1)#是按每行来求平均值
0    59214.70
1    59188.66
2    59183.70
dtype: float64
  • iloc属性用于根据位置获取值
#1)查询元素
salesDf.iloc[0,1]
'001616528'

#2)获取第一行
salesDf.iloc[0,:]
购药时间    2018-01-01 星期五
社保卡号         001616528
商品编码            236701
商品名称           强力VC银翘片
销售数量                 6
应收金额              82.8
实收金额                69
Name: 0, dtype: object

#3)获取第一列
salesDf.iloc[:,0]
0    2018-01-01 星期五
1    2018-01-02 星期六
2    2018-01-06 星期三
Name: 购药时间, dtype: object
  • loc属性根据索引获取值
#1)查询元素
salesDf.loc[0,'商品编码']
236701

#2)获取第一行
salesDf.loc[0,:]
购药时间    2018-01-01 星期五
社保卡号         001616528
商品编码            236701
商品名称           强力VC银翘片
销售数量                 6
应收金额              82.8
实收金额                69
Name: 0, dtype: object

#3)获取第一列
salesDf.loc[:,'商品名称']
0    强力VC银翘片
1    清热解毒口服液
2         感康
Name: 商品名称, dtype: object

#4)列表功能:以插入列表的形式查询某几列:
salesDf[['商品名称','销售数量','实收金额']]
商品名称 销售数量 实收金额     
0 强力VC银翘片 6 69.00   
1 清热解毒口服液 1 24.64   
2 感康 2 15.00    

#5)切片功能:以切片的形式指定某两列之间的范围
salesDf.loc[:,'商品名称':'实收金额']
商品名称 销售数量 应收金额 实收金额     
0 强力VC银翘片 6 82.8 69.00   
1 清热解毒口服液 1 28.0 24.64   
2 感康 2 16.8 15.00    
  • 通过条件判断筛选
#1)构建查询条件
querySer=salesDf.loc[:,'销售数量']>1
type(querySer)
pandas.core.series.Series
querySer#得到的是pandas的一维数组(Series),值是布尔类型
0     True
1    False
2     True
Name: 销售数量, dtype: bool

#2)应用查询条件
salesDf.loc[querySer,:]
购药时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额     
0 2018-01-01 星期五 001616528 236701 强力VC银翘片 6 82.8 69.0   
2 2018-01-06 星期三 0012602828 236701 感康 2 16.8 15.0    
数据集描述统计信息

#1)读取Excel数据
fileNameStr='E:\我要成为一名数据分析师\猴子聊人物\跟猴子学习人工智能核心技术\数据分析(中级)(Python)\第3关:数据分析的基本过程\朝阳医院2018年销售数据.xlsx'
xls=pd.ExcelFile(fileNameStr)
salesDf=xls.parse('Sheet1')#parse代表读取

#2)打印前5行
salesDf.head()#head()只取前5行,tail()是取后5行
购药时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额     
6573 2018-04-27 星期三 1.078861e+08 2367011.0 高特灵 10.0 56.0 54.80   
6574 NaN NaN NaN NaN NaN NaN NaN   
6575 2018-04-27 星期三 1.008787e+10 2367011.0 高特灵 2.0 11.2 9.86   
6576 2018-04-27 星期三 1.340663e+07 2367011.0 高特灵 1.0 5.6 5.00   
6577 2018-04-28 星期四 1.192693e+07 2367011.0 高特灵 2.0 11.2 10.00 
   
#3)查看列的数据类型:dtype
salesDf.loc[:,'销售数量'].dtype
dtype('float64')

#4)有多少行,多少列 shape
#有多少行 shape[0]
#多少列 shape[1]
print(salesDf.shape)
print(salesDf.shape[0])
print(salesDf.shape[1])
(6578, 7)
6578
7

#5)每一列的统计数
salesDf.describe()
社保卡号 商品编码 销售数量 应收金额 实收金额     
count 6.576000e+03 6.577000e+03 6577.000000 6577.000000 6577.000000   
mean 6.091254e+09 1.015869e+06 2.386194 50.473803 46.317510   std 4.889284e+09 5.131153e+05 2.375202 87.595925 80.976702   
min 1.616528e+06 2.367010e+05 -10.000000 -374.000000 -374.000000   
25% 1.014234e+08 8.614560e+05 1.000000 14.000000 12.320000   
50% 1.001650e+10 8.615070e+05 2.000000 28.000000 26.600000   
75% 1.004882e+10 8.690690e+05 2.000000 59.600000 53.000000   
max 1.283612e+10 2.367012e+06 50.000000 2950.000000 2650.000000 

3、案例销售数据

数据分析的基本过程:
1、提出问题(明确实际问题)
2、理解数据(采集数据,导入数据,查看分析数据的整体信息,字段信息)
3、数据清洗
4、构建模型(简单的分析得出一些业务指标,复杂的分析运用机器学习的算法训练模型)
5、数据可视化

1)、提出问题

业务指标一:月均消费次数
业务指标二:月均消费金额
业务指标三:客单价
业务指标四:消费趋势

2)、理解数据

#1)读取Excel数据
#读取Excel数据,统一先按照object(字符串str)读入,保证数据读取正确,之后转换
fileNameStr='E:\我要成为一名数据分析师\猴子聊人物\跟猴子学习人工智能核心技术\数据分析(中级)(Python)\第3关:数据分析的基本过程\朝阳医院2018年销售数据.xlsx'
xls=pd.ExcelFile(fileNameStr,dtype='object')
salesDf=xls.parse('Sheet1',dtype='object')#parse代表读取

#2)打印前5行,查看数据读取是否正确
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   
 
#3)查看数据类型
salesDf.dtypes
购药时间    object
社保卡号    object
商品编码    object
商品名称    object
销售数量    object
应收金额    object
实收金额    object
dtype: object

3)、数据清洗

数据清洗步骤: 选择子集 ——列名重命名——缺失数据处理——数据类型转换——数据排序 ——异常值处理

#1)选择子集(本案例不需要选择子集)
subsalesDf=salesDf.loc[0:4,'购药时间':'销售数量']
''' 这里与salesDf.iloc[0:4,'购药时间':'销售数量']得到的数据不同,是由于iloc与loc的获取值的方式不同造成的。 具体情况参考如下(其中还有对ix[]的介绍): https://stackoverflow.com/questions/31593201/pandas-iloc-vs-ix-vs-loc-explanation-how-are-they-different '''
subsalesDf
购药时间 社保卡号 商品编码 商品名称 销售数量     
0 2018-01-01 星期五 001616528 236701 强力VC银翘片 6   
1 2018-01-02 星期六 001616528 236701 清热解毒口服液 1   
2 2018-01-06 星期三 0012602828 236701 感康 2   
3 2018-01-11 星期一 0010070343428 236701 三九感冒灵 1   
4 2018-01-15 星期五 00101554328 236701 三九感冒灵 8    

#2)列名重命名
#字典:旧列名和新列名对应关系
colNameDict={'购药时间':'销售时间'}
salesDf.rename(columns=colNameDict,inplace=True)
''' inplace=False,数据框本身不会变,而会创建一个新的数据框,默认的inplace为False 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    

#3)缺失数据处理
print('删除缺失值前大小:',salesDf.shape)
删除缺失值前大小: (6578, 7)
#删除列(销售时间,社保卡号)中为空的行
salesDf=salesDf.dropna(subset=['销售时间','社保卡号'],how='any')#subset指定删除列的列表,how指定如何删除数据
print('删除缺失值后大小:',salesDf.shape)
删除缺失值后大小: (6575, 7)

#4)数据类型转换
#字符串转换为数值(浮点数)
salesDf['销售数量']=salesDf['销售数量'].astype('float')
salesDf['应收金额']=salesDf['应收金额'].astype('float')
salesDf['实收金额']=salesDf['实收金额'].astype('float')
print('转换后的数据类型:\n',salesDf.dtypes)
转换后的数据类型:
 销售时间     object
社保卡号     object
商品编码     object
商品名称     object
销售数量    float64
应收金额    float64
实收金额    float64
dtype: object

#字符串分割split
testList='2018-06-03 星期五'.split(' ')
testList
['2018-06-03', '星期五']
testList[0]
'2018-06-03'

''' 定义函数:分割销售日期,获取销售日期 输入:timeSer销售时间这一列,是一个Series数据类型 输出:分割后的时间,返回也是个Series的数据类型 '''
def splitSaletimen(timeSer):
    timeList=[]
    for value in timeSer:
        dateStr=value.split(' ')[0]
        timeList.append(dateStr)
    timeSer3=pd.Series(timeList)
    return timeSer3

#获取销售时间这一列
timeSer2=salesDf.loc[:,'销售时间']

#对字符串进行分割,获取销售日期
timeSer4=splitSaletimen(timeSer2)
timeSer4[0:3]
0    2018-01-01
1    2018-01-02
2    2018-01-06
dtype: object

#修改销售时间这一列的值
salesDf.loc[:,'销售时间']=timeSer4

#查看前5行销售时间
salesDf.loc[:,'销售时间'].head()
0    2018-01-01
1    2018-01-02
2    2018-01-06
3    2018-01-11
4    2018-01-15
Name: 销售时间, dtype: object

#format 是你原始数据中日期的格式
#errors='coerce'代表原始数据不符合日期的格式,转换后的值为NaT
salesDf.loc[:,'销售时间']=pd.to_datetime(salesDf.loc[:,'销售时间'],format=('%Y-%m-%d'),errors='coerce')
salesDf.dtypes
销售时间    datetime64[ns]
社保卡号            object
商品编码            object
商品名称            object
销售数量           float64
应收金额           float64
实收金额           float64
dtype: object

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

#5)数据排序
''' by:按那几列排序 ascending=True 表示升序排列 ascending=False 表示降序排列 '''
salesDf=salesDf.sort_values(by='销售时间',ascending=True)

#重命名行名
salesDf=salesDf.reset_index(drop=True)
salesDf.head()
销售时间 社保卡号 商品编码 商品名称 销售数量 应收金额 实收金额     
0 2018-01-01 001616528 236701 强力VC银翘片 6.0 82.8 69.0   
1 2018-01-01 0010616728 865099 硝苯地平片(心痛定) 2.0 3.4 3.0   
2 2018-01-01 0010073966328 861409 非洛地平缓释片(波依定) 5.0 162.5 145.0   
3 2018-01-01 0010073966328 866634 硝苯地平控释片(欣然) 6.0 111.0 92.5   
4 2018-01-01 0010014289328 866851 缬沙坦分散片(易达乐) 1.0 26.0 23.0
    
#6)异常值处理
#删除异常值:通过条件判断筛选出数据
#查询条件
querySer=salesDf.loc[:,'销售数量']>0
print('删除异常值前:',salesDf.shape)
salesDf=salesDf.loc[querySer,:]
print('删除异常值后:',salesDf.shape)
删除异常值前: (6549, 7)
删除异常值后: (6506, 7)

4)、构建模型

业务指标一:月均消费次数

#月均消费次数=总消费次数/月份数
#删除重复数据,同一天内同一卡号刷的两笔及以上算作一笔
kpi1_Df=salesDf.drop_duplicates(subset=['销售时间','社保卡号'])
total1=kpi1_Df.shape[0]
print('总消费次数:',total1)
总消费次数: 5342

#1)排序
#按销售时间升序排序
kpi1_Df=kpi1_Df.sort_values(by='销售时间',ascending='True')

#重命名行名(index)
kpi1_Df=kpi1_Df.reset_index(drop='True')

#2)获取时间范围
#最小时间值
startTime=kpi1_Df.loc[0,'销售时间']

#最大时间值
endTime=kpi1_Df.loc[total1-1,'销售时间']

#3)计算月份数
#天数
days1=(endTime-startTime).days

#月份数:运算符‘//’表示取整除
months1=days1//30
print('月份数:',months1)
月份数: 6

#月均消费次数
kpi1_1=total1//months1
print('业务指标一:月均消费次数=',kpi1_1)
业务指标一:月均消费次数= 890

业务指标二:月均消费金额

#月均消费金额=总消费金额/月份数
#总消费金额
totalMoneyF=salesDf.loc[:,'实收金额'].sum()

#月均消费金额
monthMoneyF=totalMoneyF/months1
print('业务指标二:月均消费金额=',monthMoneyF)
业务指标二:月均消费金额= 50668.35166666666

业务指标三:客单价

#客单价=总消费金额/总消费次数
print('业务指标三:客单价=',totalMoneyF/total1)
业务指标三:客单价= 56.909417821040805

最后献上一波Jupyter NoteBook快键键使用指南:

Jupyter NoteBook 快捷键使用指南opus.konghy.cn

您的点赞是也是我前进的一份动力,希望能多多指导。

如有问题,欢迎指正。谢谢!

    原文作者:星期日
    原文地址: https://zhuanlan.zhihu.com/p/50447182
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞