import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
一、创建ndarray
1.1 通过列表和内置函数创建
# 通过列表创建
np.array([[2,3,4],[5,6,7]])
# 通过内置函数创建
np.arange(0,10,2) # 和Python里面的range一样,创建一个一维数组
np.zeros((2,3)) # 创建一个全0的 2×3 数组
np.ones((2,3),'int32') # 创建一个 2×3 的全1的数组,并且改变数组元素类型为 int32
np.full((2,3),10,'int64') # 创建一个 2×3 的指定数(这里为10)的数组,改变数组元素类型为 int64
np.empty((2,3)) # 创建一个 2×3 的空数组,只分配内存,但不填充,返回未被初始化的垃圾值
np.eye(5) # 创建一个单位矩阵数组
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
1.2 通过random函数创建
1.2.1 均匀分布
均匀分布也叫 矩形分布,它是对称概率分布,在相同长度间隔的分布概率是等可能的。
均匀分布由两个参数a和b定义,它们是数轴上的最小值和最大值,通常缩写为U(a,b)。
# 通过random函数创建
np.random.random((2,3)) # 服从均匀分布U(0,1),构建2×3的数组
array([[0.5191731 , 0.97337981, 0.43615165],
[0.26726161, 0.868919 , 0.1627226 ]])
np.random.rand(2,3) # 同上面的
array([[0.27252121, 0.09276636, 0.17518565],
[0.3519029 , 0.7170142 , 0.33306299]])
1.2.2 随机等概率
np.random.randint(0,10,(3,3)) # 随机等概率的抽取 0-9范围内的整数,构建3×3的数组
array([[0, 4, 3],
[1, 0, 2],
[5, 5, 0]])
1.2.3服从正态分布的两个随机函数
标准正态。分布期望值μ=0,即曲线图象对称轴为Y轴,标准差σ=1条件下的正态分布,记为N(0,1)。
# 标准正态分布 N(0,1)
np.random.randn(2,3)
array([[ 1.43797336, 1.2564011 , -1.98322929],
[ 0.21843254, 1.36461946, -0.92210014]])
# 正态分布 N(μ,σ^2)
np.random.normal(10,2,(2,3))
array([[ 7.7503975 , 9.37959585, 11.31247388],
[ 9.34024262, 11.74541123, 10.66043646]])
二、查看ndarray的信息
arr1 = np.random.randint(0,100,(10,10))
arr1
array([[86, 11, 50, 13, 86, 79, 72, 44, 71, 81],
[ 5, 89, 74, 23, 39, 67, 72, 23, 3, 15],
[50, 30, 68, 36, 49, 25, 64, 96, 33, 68],
[92, 41, 13, 96, 7, 20, 15, 45, 7, 46],
[70, 94, 15, 47, 58, 41, 80, 77, 37, 27],
[76, 37, 33, 31, 93, 71, 93, 8, 92, 59],
[72, 70, 65, 88, 78, 31, 52, 30, 78, 43],
[79, 22, 15, 62, 53, 67, 84, 18, 96, 95],
[14, 22, 99, 2, 60, 52, 64, 39, 9, 6],
[20, 78, 30, 50, 86, 65, 4, 48, 10, 89]])
arr1.shape # 查看数组形状
(10, 10)
arr1.ndim # 查看数组维度
2
arr1.size # 查看数组大小
100
arr1.dtype # 查看数组元素的类型
dtype('int64')
arr1.astype(np.float32) # 修改数组元素的类型,但是注意并不改变原有数组
array([[86., 11., 50., 13., 86., 79., 72., 44., 71., 81.],
[ 5., 89., 74., 23., 39., 67., 72., 23., 3., 15.],
[50., 30., 68., 36., 49., 25., 64., 96., 33., 68.],
[92., 41., 13., 96., 7., 20., 15., 45., 7., 46.],
[70., 94., 15., 47., 58., 41., 80., 77., 37., 27.],
[76., 37., 33., 31., 93., 71., 93., 8., 92., 59.],
[72., 70., 65., 88., 78., 31., 52., 30., 78., 43.],
[79., 22., 15., 62., 53., 67., 84., 18., 96., 95.],
[14., 22., 99., 2., 60., 52., 64., 39., 9., 6.],
[20., 78., 30., 50., 86., 65., 4., 48., 10., 89.]], dtype=float32)
arr1.dtype # 可以看到原有数组元素类型并没有改变
dtype('int64')
arr1.reshape(4,25) # 重构数组的形状,也是不改变原有数组
array([[86, 11, 50, 13, 86, 79, 72, 44, 71, 81, 5, 89, 74, 23, 39, 67,
72, 23, 3, 15, 50, 30, 68, 36, 49],
[25, 64, 96, 33, 68, 92, 41, 13, 96, 7, 20, 15, 45, 7, 46, 70,
94, 15, 47, 58, 41, 80, 77, 37, 27],
[76, 37, 33, 31, 93, 71, 93, 8, 92, 59, 72, 70, 65, 88, 78, 31,
52, 30, 78, 43, 79, 22, 15, 62, 53],
[67, 84, 18, 96, 95, 14, 22, 99, 2, 60, 52, 64, 39, 9, 6, 20,
78, 30, 50, 86, 65, 4, 48, 10, 89]])
三、索引操作
3.1 切片索引
arr2 = np.arange(1,10).reshape(3,3)
arr2
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
arr2[2][:2] # 先取第 3 行,然后对第三行里面的索引为0,1的列切片
array([7, 8])
arr2[1:3,:2] # arr2 [行切片,列切片],获取行下标从0到2,列下标0到1的内容
array([[4, 5],
[7, 8]])
切片说明:
list [x:y:z]
从索引x开始取,到索引为y为止,但不包括y,取值步长为z
需要注意的是,数组切片是原始数组的视图。视图上的任何修改都会直接反映到源数组上。
arr2[0][0] = 666
print(arr2)
[[666 2 3]
[ 4 5 6]
[ 7 8 9]]
当你将一个标量值赋值给一个切片时,该值会自动传播(也就说后面将会讲到的“广播”)到整个选区。
arr2[1:3,1:3] = 999
print(arr2)
arr2 = np.arange(1,10).reshape(3,3) # 为避免影响后面的内容,将arr2还原
[[666 2 3]
[ 4 999 999]
[ 7 999 999]]
当你要得到独立的原始数据副本而不是视图的时候,你可以使用copy()
s = arr2[1:3,1:3].copy()
s[:,:] = 888
print(arr2)
print(s)
[[1 2 3]
[4 5 6]
[7 8 9]]
[[888 888]
[888 888]]
并不是单纯的深复制和浅复制
3.2 花式索引
arr2
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 针对行的花式索引,取出顺序与索引顺序一致
arr2[[2,1,0]] # 这里将本来0,1,2的索引顺序取值为2,1,0
array([[7, 8, 9],
[4, 5, 6],
[1, 2, 3]])
# 针对列的花式索引,同上
arr2[:,[2,1,0]]
array([[3, 2, 1],
[6, 5, 4],
[9, 8, 7]])
# 花式索引取单个值
arr2[[1,2],[0,1]] # arr2[行,列] 取(1,0)、(2,1)对应位置的值
array([4, 8])
3.3布尔型索引
arr2 > 4 # 直接比较元素的值,生成一个True和False的ndarray对象
array([[False, False, False],
[False, True, True],
[ True, True, True]])
可以将这个ndarray对象做为索引来取其中为True的值
arr3 = arr2[arr2>4] # 取arr2中大于4的元素,但是会失去数组的形状
print(arr3)
print(type(arr3))
print(arr3.shape)
[5 6 7 8 9]
<class 'numpy.ndarray'>
(5,)
arr2[~(arr2 > 4)] # 对bool值索引取反
array([1, 2, 3, 4])
四、数组计算
Numpy的矢量化(vectorization)使得你不用编写循环就可以对数据进行批量运算。大小相等的数组之间的任何算术运算都会将运算应用到元素级。
4.1 基础计算
对应的+、-、*、/ 直接用,会应用到元素级对应的加减乘除,无需赘述
arr2 * arr2 #同shape直接运算
array([[ 1, 4, 9],
[16, 25, 36],
[49, 64, 81]])
arr2 * arr1 # 不同shape的运算会这样(不是矩阵运算)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-31-77c6c3c81a3a> in <module>()
----> 1 arr2 * arr1 # 不同shape的运算会这样(不是矩阵运算)
ValueError: operands could not be broadcast together with shapes (3,3) (10,10)
数组与标量之间的运算也是同样将标量“广播”到各个元素
arr2 * 10 # 将arr2每个元素对应的乘10
array([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])
1/arr2 # 对arr2每个元素求倒数
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667],
[0.14285714, 0.125 , 0.11111111]])
arr2**0.5 # 对arr2每个元素开方
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974],
[2.64575131, 2.82842712, 3. ]])
4.2 数组比较
同shape数组之间的比较会生成bool、型数组
arr4 = np.random.randint(1,20,arr2.shape)
arr4
array([[18, 6, 17],
[18, 8, 13],
[15, 13, 4]])
arr4 > arr2
array([[ True, True, True],
[ True, True, True],
[ True, True, False]])
不同大小的数组之间的运算叫做广播(broadcasting),后面介绍
4.3通用函数
4.3.1 一元函数:只需要一个参数
arr3
array([5, 6, 7, 8, 9])
np.abs(arr3*-1) # 绝对值
array([5, 6, 7, 8, 9])
np.sqrt(arr3) # 开方
array([2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
np.square(arr3) # 平方
array([25, 36, 49, 64, 81])
np.exp(arr3) # 指数函数,y=e^x函数
array([ 148.4131591 , 403.42879349, 1096.63315843, 2980.95798704,
8103.08392758])
# 对数函数
np.log(arr2)
np.log2(arr2)
np.log10(arr2)
array([[0. , 0.30103 , 0.47712125],
[0.60205999, 0.69897 , 0.77815125],
[0.84509804, 0.90308999, 0.95424251]])
# 三角函数
np.sin(arr2)
np.cos(arr2)
np.tan(arr2)
np.tanh(arr2) # 双弦正切
array([[0.76159416, 0.96402758, 0.99505475],
[0.9993293 , 0.9999092 , 0.99998771],
[0.99999834, 0.99999977, 0.99999997]])
print(arr2/3)
np.modf(arr2 / 3) # 将数组元素的整数和小数部分拆分,返回两个数组
[[0.33333333 0.66666667 1. ]
[1.33333333 1.66666667 2. ]
[2.33333333 2.66666667 3. ]]
(array([[0.33333333, 0.66666667, 0. ],
[0.33333333, 0.66666667, 0. ],
[0.33333333, 0.66666667, 0. ]]), array([[0., 0., 1.],
[1., 1., 2.],
[2., 2., 3.]]))
np.isnan(arr2) # 判断是否有缺失
array([[False, False, False],
[False, False, False],
[False, False, False]])
np.isinf(arr2) # 判断是否无穷
array([[False, False, False],
[False, False, False],
[False, False, False]])
4.3.2 二元函数
二元函数的第二个参数可以是标量,也可以是数组(同shape)
np.add(arr2,arr2) # 加
np.subtract(arr2,arr2) # 减
np.multiply(arr2,arr2) # 乘
np.divide(arr2,arr2) # 除
np.mod(arr2,arr2) # 取余数
np.power(arr2,3) # 开方
array([[ 1, 8, 27],
[ 64, 125, 216],
[343, 512, 729]])
4.4 线性代数
arr2.T # 转置
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
np.dot(arr2,arr4) # 矩阵内积
array([[ 99, 61, 55],
[252, 142, 157],
[405, 223, 259]])
np.diag(arr2) # 取对角线的元素
array([1, 5, 9])
np.trace(arr2) # 求迹(对角线元素之和)
15
np.linalg.det(arr2) # 求方阵的行列式
6.66133814775094e-16
np.linalg.matrix_rank(arr2) # 求矩阵的秩
2
np.linalg.eig(arr2) # 求方阵的特征值和特征向量
(array([ 1.61168440e+01, -1.11684397e+00, -1.30367773e-15]),
array([[-0.23197069, -0.78583024, 0.40824829],
[-0.52532209, -0.08675134, -0.81649658],
[-0.8186735 , 0.61232756, 0.40824829]]))
np.linalg.inv(arr2) # 求满秩方阵的逆
array([[-4.50359963e+15, 9.00719925e+15, -4.50359963e+15],
[ 9.00719925e+15, -1.80143985e+16, 9.00719925e+15],
[-4.50359963e+15, 9.00719925e+15, -4.50359963e+15]])
np.linalg.pinv(arr2) # 求伪逆
array([[-6.38888889e-01, -1.66666667e-01, 3.05555556e-01],
[-5.55555556e-02, -2.60208521e-16, 5.55555556e-02],
[ 5.27777778e-01, 1.66666667e-01, -1.94444444e-01]])
np.linalg.svd(arr2) # svd矩阵分解
(array([[-0.21483724, 0.88723069, 0.40824829],
[-0.52058739, 0.24964395, -0.81649658],
[-0.82633754, -0.38794278, 0.40824829]]),
array([1.68481034e+01, 1.06836951e+00, 1.47280825e-16]),
array([[-0.47967118, -0.57236779, -0.66506441],
[-0.77669099, -0.07568647, 0.62531805],
[ 0.40824829, -0.81649658, 0.40824829]]))
五、数据处理
5.1 条件判断
np.where(1>0,arr2,arr4)
# 判断为真输出arr2,为假输出arr4,可嵌套。arr2和arr4有相同的shape
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
5.2查看唯一值
np.unique(arr2)
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
5.3 排序
-arr2
array([[-1, -2, -3],
[-4, -5, -6],
[-7, -8, -9]])
arr5 = -np.sort(-arr2) # 排逆序
print(arr5)
[[3 2 1]
[6 5 4]
[9 8 7]]
np.sort(arr5,axis=1) # 排序,axis默认为0方向(列方向)
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
5.4判断元素存在性
np.in1d(arr2,[1,2,3])
#判断数组的元素是否在后一个list-like(ndarray-like)里面
array([ True, True, True, False, False, False, False, False, False])
六、持久化
6.1 二进制格式
np.save('path/name.npy',arr2) # 保存arr2到本地
np.load('path/name.npy') # 载入
np.savez('path/name/npz',a=arr1,b=arr2)
# 保存多个数组,读的时候也是一样的方式
6.2 文本格式
np.savetxt('path/name.txt',arr2,delimiter=',')
# 保存为文本格式,delimiter=','为用','将列隔开
np.loadtxt('path/name.txt',delimter=',')
# 读取文本文件
网友评论