一、认识和创建Numpy数组
(一)认识numpy数组对象:
NumPy中最重要的一个特点就是其N维数组对象,即ndarray(别名array)对象,该对象可以执行一些科学计算。
ndarray对象中定义了一些重要的属性。
(二)创建numpy数组
1、最简单的创建ndarray对象的方式是使用array()函数,在调用该函数时传入一个列表或者元组。
import numpy as np
arr1 = np.array([1,2,3])#这是一个一维数组
#array([1, 2, 3])
arr2 = np.array([[1,2,3],[4,5,6]])#这是一个二维数组
#array([[1, 2, 3],
# [4, 5, 6]])
2、通过zeros()函数创建元素值都是0的数组;通过ones()函数创建元素值都为1的数组。
import numpy as np
arr3 = np.zeros((3,4))
#array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
arr4 = np.ones((3,4))
'''
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
'''
3、通过empty()函数创建一个新的数组,该数组只分配了内存空间,它里面填充的元素都是随机的。
import numpy as np
arr5 = np.empty((5,2))
'''
array([[6.23042070e-307, 4.67296746e-307],
[1.69121096e-306, 4.67293691e-307],
[1.33511018e-306, 1.33511969e-306],
[6.23037996e-307, 6.23053954e-307],
[1.60218763e-306, 8.34451504e-308]])
'''
4、通过arange()函数可以创建一个等差数组,它的功能类似于range(),只不过arange()函数返回的结果是数组,而不是列表。
import numpy as np
arr6 = np.arange(1,20,5)
#array([ 1, 6, 11, 16])
有些数组元素的后面会跟着一个小数点,而有些元素后面没有,主要是因为元素的数据类型不同所导致的。
二、ndarray对象的数据类型
(一)查看数据类型
1、ndarray.dtype可以创建一个表示数据类型的对象,如果希望获取数据类型的名称,则需要访问name属性进行获取。
import numpy as np
data1 = np.array([[1,2,3],[4,5,6]])
data1.dtype.name
#name可以是int类型也可以是float类型
(1)NumPy的数据类型是由一个类型名和元素位长的数字组成。
- 通过zeros()、ones()、empty()函数创建的数组,默认的数据类型为float64。
- 默认情况下,64位windows系统输出的结果为int32, 64位Linux或macOS系统输出结果为int64,当然也可以通过dtype来指定数据类型的长度。
(2)NumPy中常用的数据类型如下表所示。
(3)每一个NumPy内置的数据类型都有一个特征码,它能唯一标识一种数据类型。
2、 ndarray对象的数据类型可以通过astype()方法进行转换。
import numpy as np
data2 = np.array([[1,3,5],[7,9,11]])
data2.dtype
#dtype('int32')
float_data2 = data2.astype(np.float64)
float_data2.dtype
#dtype('float64')
三、数组运算
(一)矢量化运算
1、数组运算可以分为以下三种:
2、形状相等的数组之间的任何算术运算都会应用到元素级,即只用于位置相同的元素之间,所得的运算结果组成一个新的数组。
(二)数组广播
1、 当形状不相等的数组执行算术计算的时候,就会出现广播机制,该机制会对数组进行扩展,使数组的shape属性值一样,这样就可以进行矢量化运算了。
2、广播机制需要满足如下任意一个条件即可:
(1)两个数组的某一维度等长。
(2)其中一个数组为一维数组。
广播机制需要扩展维度小的数组,使得它与维度最大的数组的shape值相同,以便使用元素级函数或者运算符进行运算。
(三)数组与标量间的运算
标量运算会产生一个与数组具有相同行和列的新矩阵,其原始矩阵的每个元素都被相加、相减、相乘或者相除。
四、ndarray的索引和切片
(一)整数索引和切片的基本使用
1、对于一维数组来说,从表面上来看,它使用索引和切片的方式,与Python列表的功能相差不大。
import numpy as np
arr = np.arange(8)
arr[5]
# 获取索引为5的元素
#5
arr[3:5]
# 获取索引为3~5的元素,但不包括5
#array([3, 4])
2、对于多维数组来说,索引和切片的使用方式与列表就大不一样了,比如二维数组的索引方式如下:
3、在二维数组中,每个索引位置上的元素不再是一个标量了,而是一个一维数组。
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6],[7, 8, 9]])
# 获取索引为1的元素
arr[1]
#array([4,5,6])
4、如果想获取二维数组的单个元素,则需要通过形如“arr[x,y]”的索引来实现,其中x表示行号,y表示列号。
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6],[7, 8, 9]])
# 获取位于第0行第1列的元素
arr[0, 1]
#2
5、多维数组的切片是沿着行或列的方向选取元素的,我们可以传入一个切片,也可以传入多个切片,还可以将切片与整数索引混合使用。
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6],[7, 8, 9]])
arr[:2]
#array([[1, 2, 3],
# [4, 5, 6]])
6、使用两个切片示例:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6],[7, 8, 9]])
arr[0:2,0:2]
#array([[1, 2],
# [4, 5]])
7、切片与整数索引混合使用的示例:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6],[7, 8, 9]])
arr[1,:2]
#array([[1, 2],
# [4, 5]])
(二)花式(数组)索引的基本使用
1、花式索引是NumPy的一个术语,是指用整数数组或列表进行索引,然后再将数组或列表中的每个元素作为下标进行取值。
2、如果要操作的对象是一个二维数组,则获取的结果就是对应下标的一行数据。
import numpy as np
# 创建一个二维数组
arr1 = np.empty((4, 4))
for i in range(4):
arr1[i] = np.arange(i, i + 4)
# 获取索引为[0,2]的元素
arr1[[0, 2]]
#array([[0., 1., 2., 3.],
# [2., 3., 4., 5.]])
3、如果用两个花式索引操作数组,则会将第1个作为行索引,第2个作为列索引,以二维数组索引的方式选取其对应位置的元素。
import numpy as np
arr1 = np.empty((4, 4))
for i in range(4):
arr1[i] = np.arange(i, i + 4)
arr1[[1,3],[1,2]]
#array([2., 5.])
(四)布尔型索引的基本使用
布尔型索引指的是将一个布尔数组作为数组索引,返回的数据是布尔数组中True对应位置的值。
五、数组转置和轴对称
1、数组的转置指的是将数组中的每个元素按照一定的规则进行位置变换。
NumPy提供了两种实现方式:
2、简单的转置可以使用T属性,它其实就是进行轴对换而已。
3、当使用transpose()方法对数组的shape进行调换时,需要以元组的形式传入shape的编号,比如(1,0,2)。
4、如果我们不输入任何参数,直接调用transpose()方法,则其执行的效果就是将数组进行转置,作用等价于transpose(2,1,0)。
5、有时可能只需要转换其中的两个轴,这时可以使用swapaxes()方法实现,该方法需要接受一对轴编号,比如(1,0)。
六、numpy通用函数
1、通用函数(ufunc)是一种针对ndarray中的数据执行元素级运算的函数,函数返回的是一个新的数组。
2、常见的一元通用函数如下表:
3、常见的二元通用函数如下表:
七、利用numpy数组进行数据处理
(一)将条件逻辑转为数组运算
NumPy的where()函数是三元表达式x if condition else y的矢量化版本。
import numpy as np
arr_x = np.array([1, 5, 7])
arr_y = np.array([2, 6, 8])
arr_con = np.array([True, False, True])
result = np.where(arr_con, arr_x, arr_y)
#array([1, 6, 7])
(二)数组统计运算
通过NumPy库中的相关方法,我们可以很方便地运用Python进行数组的统计汇总。
(三)数组排序
1、如果希望对NumPy数组中的元素进行排序,可以通过sort()方法实现。
import numpy as np
arr = np.array([[6, 2, 7], [3, 6, 2], [4, 3, 2]])
arr.sort()
#array([[2, 6, 7],
# [2, 3, 6],
# [2, 3, 4]])
2、如果希望对任何一个轴上的元素进行排序,则需要将轴的编号作为sort()方法的参数传入。
import numpy as np
arr = np.array([[6, 2, 7], [3, 6, 2], [4, 3, 2]])
arr.sort(0)
# 沿着编号为0的轴对元素排序
#array([[3, 2, 2],
# [4, 3, 2],
# [6, 6, 7]])
(四)检索数组元素
1、all()函数用于判断整个数组中的元素的值是否全部满足条件,如果满足条件返回True,否则返回False。
import numpy as np
arr = np.array([[1, -2, -7], [-3, 6, 2],[-4, 3, 2]])
# arr的所有元素是否都大于0
np.all(arr > 0)
#False
2、any()函数用于判断整个数组中的元素至少有一个满足条件就返回True,否则就返回False。
import numpy as np
arr = np.array([[1, -2, -7], [-3, 6, 2], [-4, 3, 2]])
# arr的所有元素是否有一个大于0
np.any(arr > 0)
#True
(五) 唯一化及其他集合逻辑
1、针对一维数组,NumPy提供了unique()函数来找出数组中的唯一值,并返回排序后的结果。
import numpy as np
arr = np.array([12, 11, 34, 23, 12, 8, 11])
np.unique(arr)
#array([ 8, 11, 12, 23, 34])
2、in1d()函数用于判断数组中的元素是否在另一个数组中存在,该函数返回的是一个布尔型的数组。
import numpy as np
arr = np.array([12, 11, 34, 23, 12, 8, 11])
np.in1d(arr, [11, 12])
#array([ True, True, False, False,
# True, False, True])
3、NumPy提供的有关集合的函数还有很多,常见的函数如下表所示。
八、线性代数模块
1、numpy.linalg模块中有一组标准的矩阵分解运算以及诸如逆和行列式之类的东西。
- 例如,矩阵相乘,如果我们通过“*”对两个数组相乘的话,得到的是一个元素级的积,而不是一个矩阵点积。
2、NumPy中提供了一个用于矩阵乘法的dot()方法。
import numpy as np
arr_x = np.array([[1, 2, 3], [4, 5, 6]])
arr_y = np.array([[1, 2], [3, 4], [5, 6]])
# 等价于np.dot(arr_x, arr_y)
arr_x.dot(arr_y)
#array([[22, 28],
# [49, 64]])
3、矩阵点积的条件是矩阵A的列数等于矩阵B的行数,假设A为 m*p的矩阵,B为 p*n 的矩阵,那么矩阵A与B的乘积就是一个 m*n 的矩阵C,其中矩阵C的第i行第j列的元素可以表示为:
4、除此之外,linalg模块中还提供了其他很多有用的函数。
九、随机数模块
1、与Python的random模块相比,NumPy的random模块功能更多,它增加了一些可以高效生成多种概率分布的样本值的函数。
- rand()函数隶属于numpy.random模块,它的作用是随机生成N维浮点数组。
import numpy as np
# 随机生成一个二维数组
np.random.rand(3, 3)
#array([[0.90058611, 0.88226587, 0.99038639],
# [0.07345557, 0.66469595, 0.7884759 ],
# [0.9268377 , 0.69002092, 0.75505384]])
2、除此之外,random模块中还包括了可以生成服从多种概率分布随机数的其它函数。
3、seed( )函数可以保证生成的随机数具有可预测性,也就是说产生的随机数相同。
numpy.random.seed(seed=None)
上述函数中只有一个seed参数,用于指定随机数生成时所用算法开始的整数值。
当调用seed()函数时,如果传递给seed参数的值相同,则每次生成的随机数都是一样的。
当传递的参数值不同或者不传递参数时,则seed()函数的作用跟rand()函数相同,即多次生成随机数且每次生成的随机数都不同。