python数据分析系列教程(2) —— Numpy模块

目录

一.Numpy简介

二.为什么引入Numpy

三.Numpy的功能

四.Numpy的基本使用

   1.创建Numpy

   2.Numpy数据类型

   3.基本索引和切片

   4.布尔型索引和花式索引

   5.数组和标量间的计算

五.数组变换

六.通用函数的使用

七.应用于数组的统计学方法

   1.基本数组统计

   2.排序

   3.生成随机数

八.numpy和线性代数


一.Numpy简介

(1)Numpy是用于高性能数学计算和数据分析的基础包,是对Python语言的扩充程序库(数值计算扩展),通过引入新的集合类型-数组,能更好的支持高维度数组和矩阵计算。

(2)主要引入了数据类型ndarray:一个具有矢量运算和复杂广播能力的快速且节省空间的多维数组,并提供了大量能为ndarray类型数据服务的,可靠的、经过检验的函数。

 (3)使用这些服务函数可以快速的进行标准函数计算、线性代数和统计学方法的函数计算,而且这些功能模块使用起来很简单,可以更便捷的进行数据的处理。

二.为什么引入Numpy

(1)引入Numpy的原因主要是因为python自带的数据类型有很大的不足,因此引入扩展包Numpy来起到扩充的作用。

       举个例子,使用列表我们可以存储一些小维度的数据类型,但是当我们想对不同列表中的数据算数操作(+、-、*)时,无法直接使用操作符对列表内元素进行计算,而只有一一遍历合并才能实现内部元素相加。

#我们想要的目标是两个元素相加
a = [1,3,5,7,9]
b = [3,5,6,7,9]

#直接相加的方式
c = a + b        
d=[]
print(c)        #输出结果是[1, 3, 5, 7, 9, 3, 5, 6, 7, 9]

#想要数值相加的方法
for i in range(len(a)):
    d.append(a[i]+b[i])
print(d)       #输出结果是[4, 8, 11, 14, 18]
(2)Nupmy不仅含有大量直接进行求均值、差方等的函数(代码更少),而且Numpy的运算速度非常的快,这是因为numpy的许多函数不仅是用C实现了,还使用了BLAS。基本上那些BLAS实现在每种操作上都进行了高度优化,例如使用AVX向量指令集,甚至能比你自己用C实现快上许多。
(3)下面两图分别是List和Array中数据索引的方式,通过图中可得知List类型是很灵活的,能存放多种类型的数据,但是元素链接太复杂,所以在进行数值计算时会比较慢。
      而Array中所有数据都具有同一类型,连线较少,Array的维度直接存储结构中,所以Array能更快的进行各种数值计算,而且能灵活的变换Array结构体的维度。










三.Numpy的功能

Numpy是一个用于进行高性能科学计算和数据分析的基础包,是数据分析中用到的其他模块(如pandas)的基础。

(1)其主要功能包括:

*创建一个具有矢量运算功能和广播功能的快速而节省空间的多维数组

*包内含有大量对整组数据进行快速运算的标准数学函数。

*提供了用于读写磁盘和操作内存映射文件的工具

*具有进行线性代数、随机数生成、傅里叶变换的功能

*可以用来集成C、C++、Fortain等语言编写的程序(提供接口)

(2)通过提供以上功能,从而能基本实现我们进行数据分析的目标功能:

*用于数据整理和清理、子集构造和过滤、转换等矢量数组运算

*常见的数组运算,如排除、唯一化、集合运算等

*数据统计和数据聚合、摘要运算

*用于异构数据集的合并、连接运算的数据对齐和关系型数据运算

*数组的分组运算(聚合、转换、函数应用)

四.Numpy的功能

   1.创建Numpy

(1)ndarray是一个N维数组对象(矩阵),其内部所有元素都必须是相同类型

(2)ndarry中主要属性包括:ndim属性(表示维度个数)、shape属性(表示各维度大小)、dtype属性(表示数据类型)

用于创建ndarry的函数包括以下几个:


通过代码实现创建为:

import numpy;
#方式一.通过转换其他类型进行创建
print('使用列表生成二维数组')
data = [[1,2],[3,4],[5,6]]
x = numpy.array(data)
print(x)       #打印数组 [[1 2][3 4] [5 6]]
print(x.ndim)  #打印数组的维度 2
print(x.shape) #打印数组各个维度的长度 (3, 2)

#方式二.使用zeros创建初始为0的数组,使用empty创建未初始化的数组
print('使用zero/ones/empty创建数组:根据shape来创建')
x = numpy.zeros(6) #创建一维长度为6的,元素都是0一维数组 
print(x)           #[ 0.  0.  0.  0.  0.  0.]    
x = numpy.zeros((2,3)) #创建一维长度为2,二维长度为3的二维0数组
print(x)           #[[ 0.  0.  0.][ 0.  0.  0.]]
x = numpy.ones((2,3)) #创建一维长度为2,二维长度为3的二维1数组
print(x)           #[[ 1.  1.  1.][ 1.  1.  1.]]
x = numpy.empty((3,3)) #创建一维长度为2,二维长度为3,未初始化的二维数组
print(x)           #[[  2.78470615e-317   2.69102854e-316   9.43952337e-317][  2.46061261e-315   2.46061261e-315   2.46061213e-315][  0.00000000e+000   0.00000000e+000   0.00000000e+000]]

#方式三.使用arange创建范围内的连续数
print('使用arange生成连续元素')   
print(numpy.arange(6))# [0,1,2,3,4,5,] 开区间
print(numpy.arange(0,6,2))  # 参数中0和6是范围,2是取值时的间隔数。 [0, 2,4]  

   2.存储数据

(1)我们在创建数组时同时会为其指定一个数据类型dtype,dtype的命名格式是:前面是类型名,后面是表示各元素位长的数字。

(2)数组的dtype块中存储将一块内存解释为指定数据类型所需要的信息,并且直接映射到相应的机器表示,所以Numpy具有强大和灵活的数据类型转换功能。

(3)Numpy可以存储大量的数据类型,包括浮点数、复数、整数、布尔值等,可支持的类型如下图:



(4)Numpy支持大量便捷的数据类型转换,比如整数型转成浮点型,浮点型转成整数型,数值字符串转换成数字(有些字符串不能转,会报错)等。

# 1.浮点型和整数型之间的转换
x = numpy.array([1,2.6,3],dtype = numpy.float64)  #([])的形式创建数组
y = x.astype(numpy.int32)
print(y) # [1 2 3]
print(x) # [ 1.   2.6  3. ]
z = y.astype(numpy.float64)
print(z) # [ 1.  2.  3.]

# 2.将字符串元素转换为数值元素
x = numpy.array(['1','2','3'],dtype = numpy.string_)
x1 = numpy.array(['1','a','3'],dtype = numpy.string_)
y = x.astype(numpy.int32)
#y1 = x1.astype(numpy.int32)  #无法进行转换    Error:invalid literal for int() with base 10: 'a'
print(x) # ['1' '2' '3']
print(y) # [1 2 3] 

# 3.以其他数组类型作为参照进行转化
x = numpy.array([ 1., 2.6,3. ],dtype = numpy.float32);
y = numpy.arange(3,dtype=numpy.int32);
print(y)                 # [0 1 2]
print(y.astype(x.dtype)) # [ 0.  1.  2.]

   3.基本索引和切片

(1)对数组的索引分为两种方式,分别是对一维和多维数组的索引。

*对一维数组的索引与Python的列表索引功能相似,直接使用序号索引即可。

*对多维数组的索引要考虑到维度的问题,可以使用[]对不同维度序号分别放置(如a[维度1序号][维度2序号]...),也可以在[]中直接放置所有维度的序号(如a[维度1序号,维度2序号...])

#对单维数组索引
x = numpy.array([1,2,3,4])
print(x[0])   # 对单维数组,直接给予索引号即可   输出1
#对多维数组索引
y = numpy.array([[1,2],[3,4],[5,6]])
print(y[0])    # 对多维数组的一种索引方式,输出[1 2]
print(y[0][1]) # 对多维数组的二维索引,输出2
print(y[0,1])  # 与上一种方法等价的索引方式,输出2

(2)对数组的切片

对数组的切片与Python中针对列表的切片方式基本类似,也分为针对一维和多维的切片方式。

*对一维数组切片,直接使用 数组名[start:end]的形式即可,不取到最后的end。

*对多维数组切片时,方式上可以分为对一个轴和多个轴切片的不同方式,对一个轴切片时,就类似于一维的数组名[start:end]即可。对多个轴切片时,是将整数索引混合使用的,如对二轴切片时,形式为数组名[start:1end1,start2:end2]分别在第一轴和第二轴上限定范围。

#对一维数组的切片
x = numpy.array([1,2,3,4,5])
print(x[1:3])  # [2,3]     右边开区间
print(x[:3])   # [1,2,3]   左边默认为 0
print(x[1:])   # [2,3,4,5] 右边默认为元素个数
print(x[0:4:2])# [1,3]     切片时下标递增2

#对多维数组的切片
x = numpy.array([[1,2],[3,4],[5,6]])
print(x[:2])   # [[1 2],[3 4]] 在一个轴上进行切片
print(x[:2,:1])# [[1],[3]]     在两个轴上分别进行切片
x[:2,:1] = 0   # 用标量赋值     根据切片位置进行赋值
print(x)       # [[0,2],[0,4],[5,6]]
x[:2,:1] = [[8],[6]] # 用数组对切片位置进行赋值改变   
print(x)       # [[8,2],[6,4],[5,6]]

   4.布尔型和花式索引

(1)布尔索引是指使用布尔型数组作为数组的索引项,并且布尔型数组的长度必须跟被索引的轴长度一致,进行索引时的组合形式是:被索引数组[布尔型数组],索引时会将对应位为True的位置保留下来。

#使用布尔数组进行索引,两个数组长度都是6
x = numpy.array([3,2,3,1,3,0])
y = numpy.array([True,False,True,False,True,False]) 
print x[y] # [3,3,3] 

#对布尔值判断后的索引方式
print x[y==False] # [2,1,0]

#对原数组加上运算符操作条件,可以产生新的布尔数组
print x>=3 # [ True False  True False  True  False]
print (x==2)|(x==1) # [False  True False  True False False]

#所用(x==2)|(x==1)计算下,新产生的[False  True False  True False False]布尔数组最为索引索引数组,对目标数组记性索引
print x[(x==2)|(x==1)]# 输出索引结果:[2 1]
x[(x==2)|(x==1)] = 0  # 根据索引数组索引的结果进行按位赋值
print x # 输出[3 0 3 0 3 0]

(2)花式索引是使用整数数组作为索引方式,进行索引时的方式是:被索引数组[整型数组],放置整数数组时,类似于基本索引又可分为单轴和多轴的索引方式。

#单轴上的花式索引
x = numpy.array([1,2,3,4,5,6])
print(x[[0,1,2]])    # 找出数组上的对应位置,打印:[1 2 3]
print(x[[-1,-2,-3]]) # 反向索引,打印:[6,5,4]

#针对多维数组的单、多轴花式索引
x = numpy.array([[1,2],[3,4],[5,6]])
print(x[[0,1]])          # 单轴索引,打印:[[1,2],[3,4]]
print(x[[0,1],[0,1]])    # 二轴索引,非:方式  打印:x[0][0]和x[1][1]:[1,4] 
print(x[[0,1]][:,[0,1]]) # 打印0和1行的01列 打印:[[1,2],[3,4]]

    5.数组和标量间的计算

由于Numpy中的数组都是矢量化(无须循环就能对数据进行批量运算)过的,所以对大小相等数组的任何算术运算都会应用到元素级,因此对数组进行标量计算是非常便捷的,不像普通Python中需要执行循环。
#数组单目运算
x = numpy.array([1,2,3]) 
print(x*2) # [2 4 6]
print(x>2) # [False False  True]
#数组双目运算
y = numpy.array([3,4,5])
print(x+y) # [4 6 8]
print(x>y) # [False False False]
print(x*y) # [ 3  8 15]
print(x**y)#[  1  16 243]

五.数组转换

    数组维度变换和轴转化是数据分析中对数据常用的一种操作方式,对数组的转换包括维度的重置、转置、轴变换等操作。但要注意对数组进行transpose等操作时,操作并不会对原数组进行变换,而是返回变换后的结果,是一个视图。

(1)进行维度变换和一些转置。

b = numpy.array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11]],
           [[12, 13, 14, 15],
            [16, 17, 18, 19],
            [20, 21, 22, 23]]])
print(b.shape)        #打印原shape为 (2, 3, 4)

# 1.ravel函数用于将数组平展开,创建视图
print(b.ravel())      #输出:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,14, 15, 16,17, 18, 19, 20, 21, 22, 23])

# 2.flatten将数组展开,创建一个拷贝,拷贝结果会影响原数组
b.flatten()           #输出:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,14, 15, 16,17, 18, 19, 20, 21, 22, 23])

# 3.reshape 用于设置数组形状,总数必须一致
print(b.reshape(6,4)) #输出:array([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11],[12, 13, 14, 15],[16, 17, 18, 19],[20, 21, 22, 23]])

# 4.用于转置矩阵,由原来的(2,3,4)转置成(4,3,2),内部元素布置也发生变换
print(b.transpose())  #输出:array([[[ 0 12],[ 4 16],[ 8 20]],[[ 1 13],[ 5 17],[ 9 21]],[[ 2 14],[ 6 18],[10 22]],[[ 3 15],[ 7 19],[11 23]]])

(2)使用swapaxes函数进行轴变换,返回得到数组的视图。

# 5.对形状为(6,4)的c数组进行轴变换   swapaxes接受两个轴编号,针对轴编号进行变换,swapaxes(0,1)意思是将0轴和1轴进行交换
c=numpy.array([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11],[12, 13, 14, 15],[16, 17, 18, 19],[20, 21, 22, 23]])
print(c.shape) # 6,4
print(c.swapaxes(1,0)) #输出:[[ 0  4  8 12 16 20] ,[ 1  5  9 13 17 21], [ 2  6 10 14 18 22], [ 3  7 11 15 19 23]]

六.通用函数的使用

    通用函数是数组进行元素级运算的函数,对数组的运算包括一元、二元函数运算,对数组的矢量运算直接作用到内部元素上

(1)一元运算包括以下函数:

实现上:

#计算元素平方
x = numpy.array([1.5,1.6,1.7,1.8])
print(numpy.square(x)) # [ 0  1  4  9 16 25]

#进行小数和整数部分的分离
y,z = numpy.modf(x)
print(y) # [ 0.5  0.6  0.7  0.8]    #分离出的小数部分
print(z) # [ 1.  1.  1.  1.]        #分离出的整数部分

#计算元素平方根
print(numpy.sqrt(x)) # [ 1.22474487  1.26491106  1.30384048  1.34164079]

#计算反三角函数
print(numpy.cos(x)) #  [ 0.0707372  -0.02919952 -0.12884449 -0.22720209]

(2)二元运算包括以下函数:


实现上:

x = numpy.array([[1,4],[6,7]])
y = numpy.array([[2,3],[5,8]])

#对数组按最大的取数
print(numpy.maximum(x,y)) # [[2,4],[6,8]]

#对数组按最小的取数
print(numpy.minimum(x,y)) # [[1,3],[5,7]]

#对数组按位相乘
print(numpy.multiply(x,y)) # [[ 2 12],[30 56]]

#对数组取模运算
print(numpy.mod(x,y)) # [[1 1],[1 7]]

七.应用于数组的统计学方法

   1.基本数组统计

    Numpy可以通过数学函数对整个数组或者某一轴向进行统计计算,常见的统计计算包括求和、均方差、最大最小等统计方法。



 在实现上:

x = numpy.array([[1,2],[3,3],[1,2]]) #同一维度上的数组长度须一致
print(x.mean())       # 求均值为2
print(x.mean(axis=1)) # 对每一行的元素求平均为[ 1.5  3.   1.5]
print(x.mean(axis=0)) # 对每一列的元素求平均为[ 1.66666667  2.33333333]
print(x.sum())        # 对所有项求和 12
print(x.sum(axis=1))  # 每行上求和[3 6 3]
print(x.max())        # 所有项中最大的:3
print(x.max(axis=1))  # 每行上最大:[2 3 2]
print(x.cumsum())     # 逐个把每一项相加获取结果 [ 1  3  6  9 10 12]
print(x.cumprod())    # 逐个把每一项相乘获取结果 [ 1  2  6 18 18 36]

   2.排序

    Numpy可以针对数组进行正方向排序,对单个行或列进行排序,有选择的使用快排、堆排等方式进行排序。

   (1)最简单的方式是使用sorted函数进行排序,默认是由小到大进行排序,其函数形式如下。
sort(a, axis=1, kind='quicksort', order=None)
a:所需排序的数组 、
axis:是数组排序时的基准,axis=0axis=0,按行排列;axis=1axis=1,按列排列 .
kind:数组排序时使用的方法, 'quicksort'为快排'、‘mergesort’为混排、‘heapsort’为堆排序。
      order:一个字符串或列表,可以设置按照某个属性进行排序
代码实现上:
array1=numpy.array([[4,3,2],[2,1,4]]) 
print(array1)  #输出[[4, 3, 2],[2, 1, 4]]

#按行进行排序
array1.sort(axis=1)
print(array1)  #按行进行排序,输出[[2 3 4],[1 2 4]]

#按列进行排序
array1.sort(axis=0)
print(array1)  #按列进行排序,输出[[1 2 4],[2 3 4]]

np.sort(array1, axis=None)#当axis=None,将所有元素统一排序
print(array1)

#使用快速排序法,在列上进行排序
array1.sort(axis=0,kind='quicksort')
print(array1)  #按列进行排序,输出[[1 2 4],[2 3 4]]

    (2)也可以使用sorted函数进行排序,sorted函数可对所有可迭代的对象进行排序操作,它与sort的区别是sort是应用于list上的方法,而sorted可以对所有可迭代的对象进行排序,并且sorted不会对本身进行操作, 会返回视图,而不会改变原来的数组。

     另外在sorted方法中可以利用参数reverse=True进行反向排序。

list=[3,4,2,6,1]
print(sorted(list))         #直接进行排序 输出为:[1, 2, 3, 4, 6]
print(list)                 #进行sorted后对本身并不会产生影响,输出为 :[3, 4, 2, 6, 1]
sorted(list, reverse=True) #选择进行反向排序,由大到小,输出为:[6, 4, 3, 2, 1]

3.生成随机数  

   Numpy中包含许多用于生成各种概率分布样本的函数,如生成随机数、正态分布样本、二项分布、均匀分布样本等的函数。



实现代码:

import numpy as np
from numpy import random as nr
#只显示小数点后两位 设置生成数的精度
np.set_printoptions(precision = 2)

#1.生成0-1之间的负点随机数
r1 = nr.rand(3,4)
print(r1) #[[ 0.34  0.51  0.65  0.57],[ 0.97  0.16  0.62  0.37],[ 0.23  0.78  0.77  0.46]]

#2.生成标准正态分布数(平均值为0,标准差为1)
r2 = nr.randn(2,3)
print(r2) #[ 0.16 -1.41 -0.75],[-0.45  0.34  0.36]]

#3.生成0-10内的随机数
r3 = nr.randint(0,10,size = (2,4))
print(r3) #[[6 9 3 1],[1 6 9 6]]
 
#4.定义生成高斯分布样本,第一个参数是均值,第二个参数是标准差,shape为(3,4)形式
r1 = nr.normal(100,10,size = (3,4))
print(r1) #[[ 100.71   97.51   87.9   114.81],[ 101.64  110.04   75.9    87.98],[  95.79  103.21  115.58  107.55]]
 
#5.生成均匀分布的样本,前两个参数分别是区间的初始值和终值
r2 = nr.uniform(0,10,size = (3,4))
print(r2) #[[ 0.84  4.08  2.52  6.69],[ 9.45  2.53  8.5   3.29], [ 0.28  7.6   1.    8.35]]

八.numpy和线性代数

  每个数组都可以看成是一个矩阵,因此应用于数组的矩阵分解,矩阵点乘,矩阵求逆方法对数组也是实用的,因此Numpy中有大量用于数组的矩阵操作,常见的操作如下图:

代码实现:

import numpy.linalg as nla

print('矩阵点乘')
x = numpy.array([[1,2],[3,4]])
y = numpy.array([[1,3],[2,4]])
print(x.dot(y))       # 矩阵相乘的方式一 [[ 5 11][11 25]]
print(numpy.dot(x,y)) # 矩阵相乘的方式二 [[ 5 11][11 25]]

print('矩阵求逆')
x = numpy.array([[1,1],[1,2]])
y = nla.inv(x)   # 矩阵求逆(若矩阵的逆存在) 输出为[[ 1.  0.],[ 0.  1.]]
print(y)         # 求得逆矩阵为:[[ 2. -1.],[-1.  1.]]
print(x.dot(y))  # 矩阵点乘逆矩阵得到单位矩阵: [[ 1.  0.][ 0.  1.]]

猜你喜欢

转载自blog.csdn.net/maqunfi/article/details/79655898