Numpy,也就是Numerical Python。
Numpy的核心特征之一是N-维数组对象ndarray。下面代码使用标准的方式导入Numpy包,并生成小的随机数组(2行3列)。每一个数组都有一个shape属性,用来表征数组每一维度的数量; 每一个数组都有一个dtype属性,用来描述数组的数据类型。
import numpy as np
data = np.random.randn(2, 3)
print(data)
print(data*10)
print(data+data)
print(data.shape)
print(data.dtype)
np.arange方法的使用方法:
参数个数情况: np.arange()函数分为一个参数,两个参数,三个参数三种情况
1)一个参数时,参数值为终点,起点取默认值0,步长取默认值1。
2)两个参数时,第一个参数为起点,第二个参数为终点,步长取默认值1。
3)三个参数时,第一个参数为起点,第二个参数为终点,第三个参数为步长。其中步长支持小数。
1. ndarray多维数组对象
1.1 生成ndarray
生成数组最简单的方式就是使用array函数。除此之外,zeros可以一次性创造全0数组,ones可以一次性创造全1数组。empty则可以创建一个没有初始化数值的数组。arange是Python内建函数arange的数组版。
data1 = [6, 5.3, 5.9, 17]
data3 = [[1, 67, 23, 54], [3, 24, 65, 45]] # 为了保证生成ndarray,每行的列数应该一致
arr1 = np.array(data1)
arr3 = np.array(data3)
print("\narr3的信息:---------------")
print(arr3)
print(arr3.shape)
print(arr3.ndim)
print(arr3.dtype)
arr4 = np.zeros(5)
arr5 = np.ones(5)
arr5 = np.empty(5)
arr6=np.zeros((4,3)) # 生成高维数组,需要将元组传给zeros。(4,3)
arr7=np.arrange(15) # 类似python的arange
1.2 ndarray的数据类型:
数据类型,即dtype。dtype是NumPy能够与其他系统数据灵活交互的原因。dtype类型命名方式是:类型名,比如float和int,后面再接上表明每个元素位数的数字,例如float64。常用的数据类型记住:int64,float64,bool,string_,object,详细的可以在网上查找。可以使用astype方法来显示地转换数据类型。
使用astype时,总是生成一个新的数组,即使传入的dtype与之前一致。
arr9 = np.array([1,2,3], dtype = np.float64)
arr10 = np.array([1,2,3], dtype = np.int64)
arr11 = arr10.astype(np.float64) # 显示地转换类型
1.3 Numpy数组算术:
Numpy允许批量操作而无需for循环,这是很方便的方面,这种特性叫做向量化。任何2个等尺寸数组之间的算术操作都应用了逐元素操作的方式,记住这种不是矩阵计算。不同尺寸的数组间的操作,将会用到广播特性。
arr12 = np.array([[1,2,3],[4,5,6]])
print(arr12*0.5)
print(arr12*arr12)
1.4 基础索引和切片
数组的切片是原数组的视图。任何对于视图(array切片)的修改都会反映到原数组上。如果想要一份数组切片的拷贝而不是一份视图的话,调用copy()方法。对于高维数据,访问方法arr14[0,1]和arr14[0][1]的作用是一致的。
arr13 = np.arange(7)
arr13_slice1 = arr13[1:3] # 切片范围是左开右闭,例如这个实际上的寻址序列是[2,4) 结果是:array([1, 2])
print(arr13)
print(arr13_slice1)
arr13_slice1[:] = 666 # 任何对于视图(array切片)的修改都会反映到原数组上
print(arr13)
arr13_slice2 = arr13[1:5].copy() # copy()得到数组切片的拷贝而不是一份视图
arr13_slice2[:] = 888
print(arr13_slice2)
print(arr13)
arr14 = np.array([[1,2],[3,4]])
print(arr14[0,1])
print(arr14[0][1])
1.5 布尔索引
numpy.random.randn(d0, d1, ..., dn) 从“标准正态”分布中返回一个样本(或样本)。后边接几个参数,就是几维数组。如果没有参数,则返回从分布中随机抽样的单个float。
布尔型数组,可以用于数组索引,布尔型数组的长度必须和被索引的轴的长度一致。布尔型数组可以和切片、整数混合使用。可以使用!= 来表示“不等于”,例如“ arr15[names!='Bob',:2]”,使用&表示和,使用|表示或,例如:“ arr15[(names=='Bob')|(names == 'Lucy'),:2]”。通过布尔型数组选取数组的中数据,总是创建数据的副本。
解释: (names=='Bob').shape 的结果是 (7,); arr15.shape的结果是 (7, 5) 两者的第一个dimension都是7,所以是合法的,否则不合法。
names = np.array(['Bob','Jane','Lucy','Bob','Jim','Lucy','Bob'])
arr15 = np.random.randn(7,5)
arr15[names == 'Bob']
arr15[names=='Bob',:2]
arr15[names!='Bob',:2]
arr15[(names=='Bob')|(names == 'Lucy'),:2]
arr15[arr15<0]=0
1.6 数组索引(已array为索引,在每个维度选择几行)
就是将一个array作为数组的索引。arr16[[4,3,0,2,1]]表示分别返回第4,3,0,2,1行并组成一个新的array(选取这些行)。其实也就是按照每个dimension选多行。
arr16 = np.arange(16).reshape(4,4)
print(arr16)
print(arr16[[0,2]]) # 选择第一行和第3行
print(arr16[[0,2]][:,[1,3]]) # 选择第1,3行,并且第2,4列
1.7 数组转置和换轴
转置操作类似于矩阵的转置(当数组是二维时),可以使用ndarray的T属性,也可以使用transpose()方法。下面介绍下transpose()方法,对于一个n维数组,原始的序列顺序是 0,1,2,...,n-1,那么输入给transpose()方法的,也是这些维度序列顺序的一个重新排列。例如三维数组原始的排序方式是0,1,2 那么arr.transpose(0,2,1) 实际上就是把第3维和第2维调整了下,第1维不变。 这种同样可以写成 arr.swapaxes(1,2)调转第2,3维。另外,np.dot(arr1,arr2) 可以实现矩阵乘法。
arr17=np.arange(15).reshape(5,3)
print(arr17)
print(arr17.T) # T求多维数组的转置
print(arr17.transpose(1,0)) # transpose更加灵活,可以转置多维数组。arr17有2个维度,从 0,1 -> 1,0
print( np.dot(arr17,arr17.T)) # np.dot接收2个多维数组为参数,计算矩阵乘法。
arr18 = np.arange(16).reshape(2,2,4)
print(arr18)
print(arr18.transpose(0,2,1))
print(arr18.swapaxes(1,2)) # 换轴操作,等同于arr18.transpose(0,2,1)
2. 通用函数
通用函数,也称为ufunc,是比较简单的。只要记住是在ndarray数据中进行逐元素操作的函数即可。包含一些一元函数,和二元函数。根据实际需求,可以具体查找使用。下面是一个简单的例子。
arr19 = np.random.randn(6)
print(arr19)
print(np.maximum(arr19,np.abs(arr19)))
3. 使用数组进行面向数组编程
np.meshgrid函数接收两个一维数组,并根据两个数组的所有(x,y)对生成一个二维矩阵。meshgrid的计算方法图解如下:
arr20 = np.arange(3)
arr21 = np.random.randn(5)
X,Y=np.meshgrid(arr20,arr21)
print(arr20)
print(arr21)
print(X)
print(Y)
3.1 将条件逻辑作为数组操作
使用np.where 实现 if bool_str: x else y的逻辑。
arr22 = np.random.randn(8)
print(arr22)
print(np.where(arr22>0,arr22,-arr22))
3.2 数学和统计方法
numpy提供了数学聚合函数,例如sum,mean等。mean和sum这类的函数可以接受一个axis参数,用于计算在该轴向上的统计值。
axis参数:
当axis=0时,对列进行聚合操作;
当axis=1时,对行进行聚合操作。
例如有一个ndarray,值为:
arr23 = array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
那么arr23.sum(1),是对横轴向上求和,那么第1,2,3行相加后得到3个值就是最终结果。array([10, 35, 60]) 。 同样的arr23.mean(0),是对纵轴向上求中位数,那么1,2,3,4,5列每一列分别求中位数,得到五个值最为最后结果,array([5., 6., 7., 8., 9.])。另外,cumsum求所有元素的累计和,cumprod求所有元素的累计积,计算原理都是一样的。
arr23 = np.arange(15).reshape(3,5)
print(arr23)
print(arr23.mean())
print(arr23.sum())
print(arr23.mean(0)) # 或者可以使用arr23.mean(axis = 0)
print(arr23.mean(1))
print(arr23.sum(axis=0))
print(arr23.sum(axis=1))
print(arr23.cumsum(axis=0))
print(arr23.cumprod(axis=1))
3.3 布尔型数组的方法
对于统计聚合函数,布尔型数组会被强转,True 强转为1 False强转为0 。例如:(arr24=='Bill').sum() 。 另外any用于测试数组是否存在一个或者多个True,而all则检查数组中是否所有值多为True。
arr24 = np.array(['Bill','Jane','Lucy','Bill','Bill','Jim'])
print(arr24 == 'Bill')
print((arr24=='Bill').sum()) # True 强转为1 False强转为0 那么sum结果为3
print((arr24=='Bill').any()) # 只要有一个是True那么就是True
print((arr24=='Bill').all()) # 所有是True才是True
3.4 排序和唯一化
numpy可以使用sort对多维数组的某个轴向排序。arr25.sort(axis=0)指二维数组按照行来排序,axis的参数和聚合统计的参数是一致的。np.unique(arr)可以对arr数组进行去重操作,np.in1d(values,vks)返回一个布尔数组,如果values数组中的元素在vks数组中为True,如果不在vks中则为False
arr25=np.random.randn(5,3)
arr25.sort(axis=0) # 将二维数组按照列来排序
print(np.unique(arr24)) # arr24 = 'Bill','Jane','Lucy','Bill','Bill','Jim'
arr26 = np.array([6,9,0,0,23,2,3,1])
print(np.in1d(arr26,[2,3,6]))
3.5 线性代数
numpy.linalg包中实现了常用的用于矩阵计算的方法,例如求矩阵的逆矩阵,矩阵的行列式,计算QR分解等等(具体查看帮助)。inv方法可以求逆矩阵,np.dot在上边已有介绍求矩阵的逆,qr是进行QR计算,下边代码中arr27_mat = arr27.T.dot(arr27)是为了将arr27转化为矩阵,也就是二维array,因为array27只是列表的array并不是矩阵,需要注意。
from numpy.linalg import inv,qr
arr27=np.arange(25).reshape(5,5)
arr27_mat = arr27.T.dot(arr27)
print(arr27_mat)
print(inv(arr27_mat))
print(arr27_mat.dot(inv(arr27_mat)))
arr27_q,arr27_r = qr(arr27_mat)
print(arr27_q)
print(arr27_r)
4.随机漫步示例程序