第二章 NumPy入门和实战
2.1 ndarray多维数组
2.1.1创建ndarray数组
ndarray是一个通用的同构数据容器,即其中的所有元素都需要是相同的类型。当创建好一个naarray数组是,同时会在内存中存储ndarray的shape和dtype。shape是ndarray维度大小的元组,dtype解释说明ndarray数据类型的对象。Numpy会为新建数据推断出一个合适的数据类型,并保存在dtype对象中。
1.zeros函数
>>>import numpy as np
# 本节只导入一次,后续不赘述
>>>np.zeros(8)
array([0., 0., 0., 0., 0., 0., 0., 0.])
>>> np.zeros((3,4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
2 ones函数
>>> np.ones(4)
array([1., 1., 1., 1.])
>>> np.ones((4,6))
array([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])
3 empty函数
>>> np.empty((2, 2, 2))
array([[[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.]]])
4 arange函数
arange函数类似于python的内置函数range,但arange函数主要用于创建数组。
>>> np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
5 eye函数
# k可选对角线的索引:0(默认值)表示主对角线,正值表示上对角线,负值表示下对角线。
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
>>> np.eye(3,k=1)
array([[0., 1., 0.],
[0., 0., 1.],
[0., 0., 0.]])
>>> np.eye(3,k=-1)
array([[0., 0., 0.],
[1., 0., 0.],
[0., 1., 0.]])
>>> np.eye(3,k=-2)
array([[0., 0., 0.],
[0., 0., 0.],
[1., 0., 0.]])
>>> np.eye(3,k=2)
array([[0., 0., 1.],
[0., 0., 0.],
[0., 0., 0.]])
>>> np.eye(3,5)
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.]])
函数列表
函数 | 使用说明 |
---|---|
arange | 类似于内置函数range,用于创建数组 |
ones | 创建指定长度或形状的全1数组 |
ones_like | 以另一个数组为参考,根据其形状和dtype创建全1数组 |
zeros、zeros_like | 类似于ones、ones_like |
empty、empty_like | 同上 |
eye、identity | 创建正方形的N*N单位矩阵 |
2.1.2 ndarray对象属性
属性 | 使用说明 |
---|---|
.ndim | 秩,即数据轴的个数 |
.shape | 数据组的维度 |
.size | 元素的总个数 |
.dtype | 数据类型 |
.itemsize | 数据中每个元素的字节大小 |
2.1.3 naarry数据类型
名称 | 解释 |
---|---|
float | 浮点 |
int | 整数 |
complex | 复数 |
bool | 布尔值 |
string_ | 字符串 |
object | 对象 |
2.1.4数组变换
1.数组重塑
import numpy as np
>>> arr = np.arange(9)
>>> arr.reshape((3,3))
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> arr = np.array([[3,4,5],[1,2,3]])
>>> arr.reshape((3,2))
array([[3, 4],
[5, 1],
[2, 3]])
>>> arr.flatten()
array([3, 4, 5, 1, 2, 3])
>>> arr.ravel()
array([3, 4, 5, 1, 2, 3])
# 传入'F'参数表示列序优先
>>> arr.flatten('F')
array([3, 1, 4, 2, 5, 3])
>>> arr.ravel('F')
array([3, 1, 4, 2, 5, 3])
#不同点:
#ravel()返回的是视图,对原来的矩阵会产生影响;
#flatten()返回的是原来矩阵的一个copy,不对原矩阵产生影响;
2.数据合并
>>> arr1 = np.arange(12).reshape(3,4)
>>> arr2 = np.arange(24).reshape(3,4)
>>> arr1
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> arr2
array([[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])
>>> np.concatenate([arr1,arr2],axis=0)
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]])
>>> np.concatenate([arr1,arr2],axis=1)
array([[ 0, 1, 2, 3, 12, 13, 14, 15],
[ 4, 5, 6, 7, 16, 17, 18, 19],
[ 8, 9, 10, 11, 20, 21, 22, 23]])
>>> np.vstack((arr1,arr2))
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]])
>>> np.hstack((arr1,arr2))
array([[ 0, 1, 2, 3, 12, 13, 14, 15],
[ 4, 5, 6, 7, 16, 17, 18, 19],
[ 8, 9, 10, 11, 20, 21, 22, 23]])
3.数据拆分
>>> t=np.arange(12).reshape(6,2)
>>> t
array([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11]])
>>> np.split(t,3)
#三等均分
[array([[0, 1],
[2, 3]]), array([[4, 5],
[6, 7]]), array([[ 8, 9],
[10, 11]])]
>>> np.split(t,2)
#二等均分
[array([[0, 1],
[2, 3],
[4, 5]]), array([[ 6, 7],
[ 8, 9],
[10, 11]])]
>>> np.split(t,[2,4])
[array([[0, 1],
[2, 3]]), array([[4, 5],
[6, 7]]), array([[ 8, 9],
[10, 11]])]
4. 数组转置和轴对换
transpose方法需要传入轴编号组成的元组
>>> tt = np.arange(12).reshape(3,4)
>>> tt.transpose((0,1))
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> tt.transpose((1,0))
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
>>> tt.T
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
>>> ttt = np.arange(16).reshape((2,2,4))
>>> ttt
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
# 如取到7这个数字,ttt[0,1,3]
>>> ttt.swapaxes(1,2)
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],
[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])
# 数字7变成ttt[0,3,1]
# swapaxes是把对应的维度交换。
# transpose是把维度按要求排列
>>> ttt.transpose((3,1,0,2))
array([[[[ 0, 2],
[ 8, 10],
[16, 18],
[24, 26]],
[[ 4, 6],
[12, 14],
[20, 22],
[28, 30]]],
[[[ 1, 3],
[ 9, 11],
[17, 19],
[25, 27]],
[[ 5, 7],
[13, 15],
[21, 23],
[29, 31]]]])
>>> ttt.swapaxes(0,2)
array([[[[ 0, 1],
[ 8, 9],
[16, 17],
[24, 25]],
[[ 4, 5],
[12, 13],
[20, 21],
[28, 29]]],
[[[ 2, 3],
[10, 11],
[18, 19],
[26, 27]],
[[ 6, 7],
[14, 15],
[22, 23],
[30, 31]]]])
2.1.5Numpy的随机数函数
函数 | 使用说明 |
---|---|
rand | 产生均匀分布的样本值 |
randint | 给定范围内随机整数 |
randn | 产生正态分布的样本值 |
seed | 随机数种子 |
permutation | 对一个序列随机排序,不改变原数组 |
shuffle | 对一个序列随机排序,改变原数组 |
uniform(low,high,size) | 产生具有均匀分布的数组,low表示起始值,high表示结束值,size表示形状 |
normal(loc,scale,size) | 产生具有正态分布的数组,loc表示均值,scale表示标准差 |
possion(lam,size) | 产生具有泊松分布的数组,lam表示随机事件发生率 |
>>> np.random.randint(100,200,size=(5,6))
array([[181, 182, 182, 102, 139, 180],
[194, 141, 102, 132, 168, 149],
[186, 158, 180, 174, 172, 116],
[124, 104, 124, 149, 157, 183],
[129, 113, 162, 146, 170, 130]])
>>> np.random.randn(2,5,6)
array([[[-1.88680515, 0.95821448, 1.56538552, -0.5029523 ,
0.46553765, -0.26989352],
[-0.57854321, 2.5977894 , -0.92817612, -0.29454443,
-0.50413816, 0.4881592 ],
[-1.26242 , 1.01485775, 1.10801176, 0.49898818,
0.0930649 , 0.36975724],
[-0.11936746, 0.17849564, -0.50486409, -0.27422916,
1.76804842, 0.66865376],
[ 1.10932313, 1.25326785, -1.02071275, 0.44196101,
0.05371912, 0.95226386]],
[[-1.97617699, -0.24237825, -0.26326995, 0.99073785,
0.66905687, 0.46722266],
[ 1.32720368, -1.11043279, -0.03776312, 1.02583984,
-2.41394845, -0.45987804],
[-1.06583129, 0.04435701, -2.07370688, -0.61290189,
-0.77538783, -0.13484703],
[ 0.62271654, 0.41820331, 1.03268801, -1.72825222,
-1.62406118, 0.72191076],
[ 0.76238038, 0.52639426, -0.2467973 , 0.38957857,
-1.38096876, -1.53196399]]])
>>> np.random.normal(4,5,size=(2,4))
array([[-3.90230987, 1.959638 , 6.70151978, 3.55868947],
[ 6.67168877, 5.01275371, 0.34331083, -0.44893952]])
2.2数组的索引和切片
2.2.1数组的索引
>>> t22 = np.arange(10)
>>> t22
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> t22[4]
4
>>> t22[-1]
9
>>> t22[-1]=13
>>> t22
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 13])
>>> t22[5:9]
array([5, 6, 7, 8])
>>> t22[:]
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 13])
# 复制数组
>>> t23 = t22.copy()
>>> t23
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 13])
# 二维数组,可在单个或多个轴向完成切片,也可以跟整数索引一起混合使用
>>> t24 = np.arange(12).reshape(4,3)
>>> t24
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
>>> t24[1]
array([3, 4, 5])
>>> t24[1][1]
4
>>> t24[1,1]
4
# 高维数组中,如省略索引,则会返回第一个维度的数组。
>>> t24[0]=5
>>> t24
array([[ 5, 5, 5],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
2.2.2数组的切片
# 使用冒号取整个轴
>>> arr = np.arange(5)
>>> arr
array([0, 1, 2, 3, 4])
>>> arr[3:4]
array([3])
>>> dt = np.arange(12).reshape(4,3)
>>> dt
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
>>> dt[2:,1]
array([ 7, 10])
>>> dt[:,1]
array([ 1, 4, 7, 10])
2.2.3布尔型索引
>>> fruits = np.array(['a','b','c','b','a','d','a'])
>>> datas = np.random.randint(-1,1,size=(7,5))
>>> datas
array([[ 0, -1, -1, 0, 0],
[-1, -1, -1, 0, -1],
[-1, -1, -1, 0, -1],
[-1, 0, -1, -1, -1],
[-1, 0, -1, 0, -1],
[ 0, 0, 0, -1, -1],
[ 0, 0, 0, 0, 0]])
>>> datas[fruits=='b']
array([[-1, -1, -1, 0, -1],
[-1, 0, -1, -1, -1]])
# 布尔型数组的长度必须和被索引的轴长度一致。
>>> datas[(fruits=='b')|(fruits=='c')]
array([[-1, -1, -1, 0, -1],
[-1, -1, -1, 0, -1],
[-1, 0, -1, -1, -1]])
>>> datas[fruits=='b',2]
array([-1, -1])
2.2.4 花式索引
>>> arr = np.arange(12).reshape(4,3)
>>> arr[[1,3,2]]
array([[ 3, 4, 5],
[ 9, 10, 11],
[ 6, 7, 8]])
>>> arr[[3,2]][:,[2,1]]
array([[11, 10],
[ 8, 7]])
>>> arr[np.ix_([3,2],[2,1])]
array([[11, 10],
[ 8, 7]])
>>> arr2 = np.arange(32).reshape((8,4))
>>> arr2
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],
[24, 25, 26, 27],
[28, 29, 30, 31]])
>>> arr2[[1,5,7,2]][:,[0,3,1,2]]
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
>>> arr2[np.ix_([1,5,7,2],[0,3,1,2])]
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
# np.ix_函数就是输入两个数组,产生笛卡尔积的映射关系。np.ix_函数,将数组[1,5,7,2]和数组[0,3,1,2]产生笛卡尔积,就是得到(1,0),(1,3),(1,1),(1,2);(5,0),(5,3),(5,1),(5,2);(7,0),(7,3),(7,1),(7,2);(2,0),(2,3),(2,1),(2,2);
2.3数组的运算
2.3.1数组和标量间的运算
>>> a=[1,2,3]
>>> b=[]
>>> for i in a:
b.append(i*10)
>>> b
[10, 20, 30]
>>> tt = np.array([1,2,3])
>>> tt
array([1, 2, 3])
>>> tt*12
array([12, 24, 36])
>>> tt+tt
array([2, 4, 6])
>>> tt*tt
array([1, 4, 9])
2.3.2通用函数
通用函数(ufunc)是一种对数组中的数据执行元素级运算的函数。
函数 | 使用说明 |
---|---|
abs | 绝对值 |
square | 求平方 |
modf | 返回元组的小数和整数部分 |
minimum | 计算元素最小值 |
2.3.3条件逻辑运算
>>> arr1 = np.array([1,3,5,7])
>>> arr2 = np.array([2,4,6,8])
>>> cond = np.array([True,False,False,True])
>>> result = [(x if c else y) for x,y,c in zip(arr1,arr2,cond)]
>>> result
[1, 4, 6, 7]
>>> result = np.where(cond,arr1,arr2)
>>> result
array([1, 4, 6, 7])
>>> arr = np.random.randint(1,300,size=(4,3))
>>> arr
array([[166, 165, 80],
[187, 119, 45],
[ 78, 101, 281],
[256, 126, 205]])
>>> np.where(arr>150,1,0)
array([[1, 1, 0],
[1, 0, 0],
[0, 0, 1],
[1, 0, 1]])
2.3.4统计运算
基本数组统计方法
函数 | 使用说明 |
---|---|
sum | 求和 |
mean | 算数平均数 |
std\var | 标准差\方差 |
min\max | 最小值\最大值 |
argmin\argmax | 最小索引\最大索引 |
cumsum | 所有元素累计和 |
cumprod | 所有元素累计积 |
2.3.5布尔型数据运算
any()检查数组是否存在True
all()检查数组是否全为True
>>> arr = np.random.randn(20)
>>> arr
array([-0.26625794, 0.74453194, -0.46339825, -1.08786548, 0.35325199,
-1.3106128 , -1.04751542, 0.22969589, 0.9714793 , -0.63165294,
0.53547653, -0.30076606, 0.1393855 , 0.62579385, 0.4737552 ,
-0.34637978, -0.30198132, -0.57528034, 0.72527849, -0.63592838])
>>> (arr<0).sum()
11
>>> (arr<0)
array([ True, False, True, True, False, True, True, False, False,
True, False, True, False, False, False, True, True, True,
False, True])
2.3.6排序
>>> arr = np.random.randn(12).reshape(4,3)
>>> arr
array([[ 0.33338228, 1.66612215, 0.74999601],
[ 0.10461774, 0.18789953, 1.06952684],
[ 1.15383401, -0.85385618, 0.75022526],
[-0.02016264, -0.27572211, 0.77425928]])
>>> tt = arr[:]
>>> ta.sort(1)
>>> ta
array([[ 0.33338228, 0.74999601, 1.66612215],
[ 0.10461774, 0.18789953, 1.06952684],
[-0.85385618, 0.75022526, 1.15383401],
[-0.27572211, -0.02016264, 0.77425928]])
>>> ta.sort(0)
>>> ta
array([[-0.85385618, -0.02016264, 0.77425928],
[-0.27572211, 0.18789953, 1.06952684],
[ 0.10461774, 0.74999601, 1.15383401],
[ 0.33338228, 0.75022526, 1.66612215]])
2.3.7 集合运算
方法 | 使用说明 |
---|---|
unique(x) | 唯一值 |
intersect1d(x,y) | 交集 |
union1d(x,y) | 并集 |
in1d | x元素是否再y元素中,返回布尔型数组 |
setdiff1d | 集合的差 |
setxor1d | 交集取反 |
>>> test = np.random.randint(1,5,10)
>>> test
array([1, 4, 3, 4, 3, 4, 2, 4, 4, 2])
>>> np.unique(test)
array([1, 2, 3, 4])
>>> kk = [1,3]
>>> np.in1d(test,kk)
array([ True, False, True, False, True, False, False, False, False,
False])
>>> kk = [1,6]
>>> np.setdiff1d(test,kk)
array([2, 3, 4])
>>> np.setxor1d(test,kk)
array([2, 3, 4, 6])
2.3.8线性代数
>>> arr1 = np.random.randint(1,10,size=(2,2))
>>> arr1
array([[1, 5],
[3, 5]])
>>> arr2 = np.random.randint(1,10,size=(5,2))
>>> arr2
array([[1, 5],
[5, 5],
[5, 8],
[2, 9],
[5, 2]])
>>> np.dot(arr2,arr1)
array([[16, 30],
[20, 50],
[29, 65],
[29, 55],
[11, 35]])
2.4数组的存储
>>> tt
array([[-0.85385618, -0.02016264, 0.77425928],
[-0.27572211, 0.18789953, 1.06952684],
[ 0.10461774, 0.74999601, 1.15383401],
[ 0.33338228, 0.75022526, 1.66612215]])
>>> np.savetxt('tt.csv',tt,fmt='%0.8f',delimiter=',')
>>> arr = np.loadtxt('tt.csv',delimiter=',')
>>> arr
array([[-0.85385618, -0.02016264, 0.77425928],
[-0.27572211, 0.18789953, 1.06952684],
[ 0.10461774, 0.74999601, 1.15383401],
[ 0.33338228, 0.75022526, 1.66612215]])
>>> np.savetxt('tt.csv',tt,fmt='%d',delimiter=',')
>>> arr = np.loadtxt('tt.csv',delimiter=',')
>>> arr
array([[0., 0., 0.],
[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]])