一、 numpy
1.1 numpy简介
numpy 提供了一种数组类型,主要是针对多维数组处理;
numpy 其中元素的数据类型是一致的,基本针对int 或 float数据处理(强一致性) 【array中数据类型不一致,强制统一数据类型 优先级顺序 str > float > int】
最原始类型: numpy.array(list)
1.2 numpy的基础操作
numpy 创建
numpy 属性:
numpy 索引和切片 详见1.5
numpy 常用操作
numpy 广播原则: 必须要保证参与运算的两个数组形状一致 # (1)缺失维度补1 (2)用已有的值填充
numpy 聚合运算: 指的是numpy提供的聚合函数
numpy 排序方式: np.sort() 与 np.partition()
1.3 numpy创建
常见参数:
# object通常指List对象 dtype指np.array对象元素类型
# copy 是否作副本拷贝 【order='K' 指的是内存序列而非排序】
# subok 针对继承类是否可见
# ndmin表示np.array维度
(1) numpy.arrary 创建 [(1)强制数据类型统一 (2)适合一维数组]
np.arrary([1, 2, 3, 4, 5]) # 格式1
np.array([1, 3.14, 'hello'], dtype='<U32') # 格式2 里面内容为字符串类型
np.arrary([1, 2, 3], [4,5,7])
(2) np.ones(shape, dtype=None, order='C') [创建多维数组 1填充] 最后一个参数为内存序不需要设置
shape = (m, n) # m行n列的二维数组
shape = (m, 1) # m行1列的二维数组 [1], [2], [3](/baibing0716/python/wiki/1],-[2],-[3)
shape = (1, m) # 1行m列的二维数组 [1, 2, 3](/baibing0716/python/wiki/1,-2,-3)
shape = (m,) # m个元素的一维数组 [1, 2, 3]
shape = (m) # m个元素的一维数组
array1 = np.ones(shape=(5, 3), dtype="float") // 5 行 3列的二维数组 默认 1.0填充
array2 = np.ones(shape=(6,), dtype="int") // 6 个元素的一维数组 1 填充
(3) np.zeros(shape, dtype=None, order='C') [创建多维数组 0填充]
array4 = np.zeros(shape=(3,)) # 一维数组(3个元素)[0. 0. 0.]
array5 = np.zeros(shape=(3,1)) # [[0.] 3行1列二维数组
[0.]
[0.]]
array6 = np.zeros(shape=(1,3)) # [0. 0. 0.](/baibing0716/python/wiki/0.-0.-0.) 1行3列二维数组
array7 = np.zeros(shape=(2,3,4),dtype='int') # 三维数组的表示
(4) np.full(shape, fill_value, dtype=None, order='C') [创建多维数组 自定义值填充]
用法同上
(5) np.eye(N, M=None, k = 0, dtype=float) [生成单位矩阵:对角线为1的矩阵]
因为是矩阵 通常情况下N == M,M控制生成矩阵的里面元素个数
k > 0 对角线向右移动 k; k < 0 对角线向左移动 k;
(6) np.linspace(start, end, num=50, endPoint=True, retstep=False,dtype=None) [构造等差数列---指定个数]
start 数列的第一项 end 数列的最后一项 num 生成的等差数列元素的个数
endPoint 构造的等差数列的时候是否包含end
retstep 是否返回指定的步长
arr = np.linspace(0, 10, 10, endpoint=False)
(7) np.arange([start,] stop, [step,] dtype=None) [构造等差数列---指定公差]
arr = np.arange(0, 5050, step = 10)
(8) np.random.randint(low, high=None, size=None, dtype=None) [生成随机数]
low 随机数的起始值 high 随机数的最大值 size 随机数的矩阵格式 区间格式: [0, 100)
r = np.random.randint(0, 100, size=(3, 5))
(9) np.random.randn(d0, d1, d2, ..., dn) [生成符合标准正态分布的数]
np.random.normal(loc, scale, size) [生成普通正态分布的数]
loc 表示期望值 scale 方差 size 生成的矩阵的图形
r1 = np.random.randn(100) [随机生成100数,这些数满足正态分布]
r2 = np.random.randn(3, 5) [随机生成3行5列的矩阵,这些数满足正态分布]
r3 = np.random.normal(loc=170, scale=5, size=(5,5))
(10) np.random.random(size) [生成的0-1范围内的随机数]
r4 = np.random.random(100) [生成100个0-1范围内的随机数 1维]
r4 = np.random.random(size=(5,5)) [生成25个0-1范围内的随机数 2维 5行5列]
(11) np.random.permutation(num) [生成随机索引--里面元素不重复]
r5 = np.random.permutation(10)
r6 = np.random.permutation(size=(5,5)) XXXXXXXX 不支持
1.4 numpy属性
numpy数组的四个属性 ndim shape size dtype
维度 矩阵形状 元素个数 元素类型
arr = np.random.randomint(0, 100, size(5, 4, 3));
print(arr.ndim) # 输出 3 np.array为3维
print(arr.shape) # 输出 (5, 4, 3) np.array最终形状
print(arr.size) # 输出 60 np.array总共有多少个元素
print(arr.dtype) # 输出 dtype='int32' np.array的【元素类型】而非对象类型 type(arr) = numpy.ndarray
1.5 numpy的索引和切片
索引访问元素: arr[m, n, ...]
索引访问行: arr[行索引]
索引访问列: arr[:, 列索引]
高级访问方式:使用list方式作为索引(索引列表、BOOL列表)
------------------------------------------------------
切片:在每一个维度上指定切片范围
arr[1:3, 1:3] 最外层 选择第2、3 最外层 - 1层 选择 2、3
-----------------------------------------------------------------------------------------------------------------------------------------
列表访问方式
一维: data = [1, 2, 3, 4] # data[0] = 1
二维: data = [1, 2, 3], [4, 5, 6](/baibing0716/python/wiki/1,-2,-3],-[4,-5,-6) # data[0] = [1, 2, 3] data[0][0] = 1
一维list的切片: data = [1, 2, 3, 4] # data[0:3] = [0, 1, 2] 切片的区间左闭右开
二维list的切片: data = [[45 39 60 90 5 96] # 切前两行 data[0:2] 行切片(默认 列的维度上不切分)
[60 82 39 72 34 63] # 切前两列 data[:, 0:2] 列切片(行的维度上不切分 所有行保留所以:,保留了所有行)
[73 33 18 76 93 60]
[61 63 92 62 92 92] # 切第三行 data[2:3] 切第3、4行 data[2:4]
[33 57 8 18 34 24]] # 切第三列 data[:, 2:3] 切第3、4列 data[:, 2:4]
-----------------------------------------------------------------------------------------------------------------------------------------
ndarray的Index是从0开始的
一维的数组:
a = np.arrange(10) # 0 1 2 3 4 5 6 7 8 9 切片函数 a[slice(2, 7, 2)] = [2, 4, 6] start, end, step 2 7 2
a[2] # 值为2
a[2:] # 值为2 3 4 5 6 7 8 9
a[2:7] # 值为2 3 4 5 6
a[2:7:2] # 值为2, 4, 6
二维的数组:
a = np.array([1,2,3,33,44],[3,4,5,66,99],[4,5,6,111,555](/baibing0716/python/wiki/1,2,3,33,44],[3,4,5,66,99],[4,5,6,111,555)) # shape = 3 * 5
a[1] # 输出[3,4,5,66,99] 取的是某一行a[n]
a[1:] # 输出[[3,4,5,66,99] 取的是从某一行开始直至最后一行的a[n:]
[4,5,6,111,555]]
a[..., 3] # 输出[33 66 111] 取的是某一列 ,分割维度
a[..., 3:] # 输出[[ 33 44] 取的是从第3列开始到最后
[ 66 99]
[111 555]]
a[:, 3] # 同上[33 66 111] 取的是某一列
a[:, 3:] # 同上[[ 33 44] 取的是从第3列开始到最后
[ 66 99]
[111 555]]
a[1, 1] # 等价于 a[1][1] = 4 (列表访问方式)a[1, 1] (numpy访问方式)
三维数组: arr3 =np.random.randint(0, 20, size=(5, 4, 3))
[[[ 6 12 6]
[ 2 16 12]
[16 2 11]
[ 8 9 8]]
[[ 2 8 6] # 访问 [ 2 8 6] arr3[1, 0] 1 表示最外层维度 0 表示最外层 -1 维度
[ 6 0 13] # 访问 13 arr3[1, 1, 2]
[14 9 14]
[ 9 6 18]]
[[12 8 3] # 切 a[2:3] 就可以得出第3块
[ 3 4 2] # 切 a[2:3, 1:2] 就可以得出第3块的第2行 a[2:3, 1:2, 2] 表示的元素即2
[ 9 11 16] # 切 a[2:3, :, 1:3] 切第3块的最后两列
[ 4 1 3]]
[[17 1 19] # 切 a[:, :, 1,3] 所有的最后两列
[14 6 12]
[10 17 16]
[18 4 6]]
[[10 9 6]
[15 19 11]
[11 16 10]
[10 4 4]]]
numpy高级访问方法
(1) arr([1, 2, 3, 4, 5]) # arr[0, 1, 2, 0, 1, 2](/baibing0716/python/wiki/0,-1,-2,-0,-1,-2) = [1, 2, 3, 1, 2, 3] 使用int型list对原arr重组
(2) arr([1, 2, 3, 4, 5]) # arr[True, False, True, False, True](/baibing0716/python/wiki/True,-False,-True,-False,-True) = [1, 3, 5] 使用bool型可以去除arr中不想要元素
# arr[arr > 3] 提取原本List中大于3的元素 结果 【4, 5】
总结:
(1)numpy[m, n, ...]中m, n都是描述的是从最外层--->最后维度的索引
(2)numpy访问的高级索引方式: (a)以int类型的list作为index进行访问 (2)以bool类型的list作为index进行访问
(3) 不论多少维,【每一个维度的切片范围都是用 “:” 表示】,【维度与维度之间递进关系用,分割】
(4)一维数据的反转 arr([1, 2, 3, 4, 5]) ======== arr[::-1]; start end step = -1 就会将整个一维数组进行反转
二维数据的反转: 行反转 arr[::-1]
列反转 arr[:, ::-1]
1.6 numpy的常用操作
(1) reshape 变形------标准写法:传入参数类型应该是一个元组
arr = np.random.randint(0, 100, size=(20)); # 一维的随机数 20个
arr.reshape((4, 5)) # reshape前后数据元素的个数必须保证一致
输出:
[70 31 41 27 66 25 14 51 52 70 38 53 19 49 65 81 59 48 76 98]
[[70 31 41 27 66]
[25 14 51 52 70]
[38 53 19 49 65]
[81 59 48 76 98]]
(2) concatenate级联
注意点:(a)级联函数的参数类型是List,且List的外部必须加()或[]
(b)级联的两个np.array的ndim维度必须相同
(c)级联的两个np.array的shape形状必须相同
(d)级联的方向控制 通过axis参数改变
(e)默认级联方向:shape位于某个tuple中的第一个值所代表的维度
arr1 = np.random.randint(0, 10, size=(3,3))
arr2 = np.random.randint(0, 20, size=(3,3))
res1= np.concatenate((arr1, arr2)) # 默认纵向级联 等价写法 res1 = np.vstack((arr1, arr2));
arr1 arr2 res1
[[6 6 8] [[ 8 1 6] [[ 6 6 8]
[3 2 5] [ 0 17 15] [ 3 2 5]
[6 3 8]] [ 4 14 5]] [ 6 3 8]
[ 8 1 6]
[ 0 17 15]
[ 4 14 5]]
res2= np.concatenate((arr1, arr2), axis=1) # 设置为横向级联 等价写法 res2 = np.hstack((arr1, arr2));
arr1 arr2 res2
[[6 6 8] [[ 8 1 6] [[ 6 6 8 8 1 6]
[3 2 5] [ 0 17 15] [ 3 2 5 0 17 15]
[6 3 8]] [ 4 14 5]] [ 6 3 8 4 14 5]]
(3) split操作
arr = np.random.randint(0, 50, size=(6,6))
part1, part2 = np.split(arr, indices_or_sections=2) # 将原np.array切分成两份 等价于 np.hsplit(arr, indices_or_sections=2)
arr part1 part2
[[48 28 6 8 20 19] [[48 28 6 8 20 19] [[20 11 0 19 18 25]
[ 8 34 28 6 13 43] [ 8 34 28 6 13 43] [24 13 23 36 34 1]
[30 13 28 42 4 45] [30 13 28 42 4 45]] [ 7 21 46 17 27 44]]
[20 11 0 19 18 25]
[24 13 23 36 34 1]
[ 7 21 46 17 27 44]]
p1, p2, p3 = np.split(part1, indices_or_sections=[2, 4], axis = 1) # indices_or_sections列表切分含义: 切分 [0:2) [2,4) [4,尾) 成这样的三份
part1 p1 p2 p3
[[48 28 6 8 20 19] [[48 28] [[6 8] [[20 19]
[ 8 34 28 6 13 43] [ 8 34] [28 6] [13 43]
[30 13 28 42 4 45]] [30 13]] [28 42]] [4 45]]
part1, part2 = np.split(arr, indices_or_sections=2, axis=1) # indices_or_sections指定切分之后的份数 axis指定切分方向 等价于 np.vsplit(arr, indices_or_sections=2)
arr part1 part2
[[48 28 6 8 20 19] [[48 28 6] [[8 20 19]
[ 8 34 28 6 13 43] [ 8 34 28] [6 13 43]
[30 13 28 42 4 45] [30 13 28] [42 4 45]
[20 11 0 19 18 25] [20 11 0] [19 18 25]
[24 13 23 36 34 1] [24 13 23] [36 34 1]
[ 7 21 46 17 27 44]] [ 7 21 46]] [17 27 44]]
(4) copy操作 生成一个np.array的副本
l1 = [1, 3, 5]
arr = np.array(l1)
copyobj = arr.copy(arr) # 生成一个arr的拷贝对象副本 修改copyobj不会影响其arr的改变
1.7 numpy聚合函数
arr = np.random.randint(0, 50, size=(10))
[25 20 20 26 37 2 34 42 8 30]
---------------------------------------------------------------------------------------------
np.sum # 求np.array对象中所有元素的【和】 arr.sum()
np.mean # 求np.array对象中所有元素的【平均值】 arr.mean()
np.prod # 求np.array对象中所有元素的【乘积结果】 arr.prod()
np.std # 求np.array对象中所有元素的【标准方差】 arr.std()
np.var # 求np.array对象中所有元素的【方差】 arr.var()
np.min # 求np.array对象中所有元素的【最小值】 arr.min()
np.max # 求np.array对象中所有元素的【最大值】 arr.max()
np.argmin # 求np.array对象中所有元素的【最小值索引】 arr.argmin()
np.argmax # 求np.array对象中所有元素的【最大值索引】 arr.argmax()
np.median # 求np.array对象中所有元素的【中位数】 arr.median()
np.percentile # 求np.array对象中所有元素的【百分位数】 看下面示例 主要用于异常值检测 然后清理离散点
np.power # 幂运算
np.any # 是否存在NAN(空值),至少存在一个则返回True boollist = arr > arr.mean(); arr[boollist]表示过滤arr中所有 > 平均值的元素
np.all # 是否全为NAN(空值),全部都是NAN则返回True
重要: (arr > 10).any() arr中是否存在 > 10的数
---------------------------------------------------------------------------------------------
方差: ((e1 - 平均值)**2 + (e2 - 平均值)**2 + ... + (en - 平均值)**2) / n
标准方差: sqrt(方差)
示例:
arr = np.arange(0, 11, step=1)
res = np.percentile(arr, [0.25, 0.5, 0.75])
print(res) # 输出 [0.025 0.05 0.075]
1.8 numpy广播机制
广播机制原则: (1)为缺失的维度补1 (2) 假定缺失元素用已有的元素进行补充
一维广播:
arr = [1, 3, 4]
a = np.array(arr)
a + 3 # 输出 [4, 6, 7]
a + 3本质:
[1, 3, 4]
[3, 3, 3] # 用已有的值补充对齐
二维广播:
m = np.ones((2, 3))
n = np.arange(3)
m + n # 输出 [[1, 2, 3],
[1, 2, 3]]
m + n本质
m n 广播机制n按已有值补全 n
[[1, 1, 1] [0, 1, 2] [0, 1, 2]
[1, 1, 1]] [0, 1, 2]
特殊形式广播:
a = np.arange(3).reshape(3,1) # 3行1列
b = np.arange(3) # 1行3列
a + b;
[[0], [0, 1, 2] === 广播机制=== [[0], [0], [0], [[0, 1, 2]
[1], [1], [1], [1] [0, 1, 2]
[2]] [2], [2], [2]] [0, 1, 2]]
乘法广播: arr * 4 指的是每个元素乘以4的结果
np.dot(arr1, arr2) 指的数学意义上的两个同阶矩阵乘法运算
1.9 numpy的排序
(1) sort排序
arr = np.array([7, 3, 6, 5, 8, 2])
arr.sort() # 方式 并不会改变原始对象 arr内部元素的顺序
np.sort(arr) # 会改变原始对象 arr内部元素的顺序
(2)partition排序
格式: np.partition(nparray对象, k) # k > 0 得到nparray对象中最小的k个数 k < 0 得到nparray对象中最大的k个数
示例: arr = np.random.permutation(10000);
np.partition(arr, 4)[:4] # 找出10000个随机数中前4个最小的数 返回List的形式
np.partition(arr, -4)[-4:] # 找出10000个随机数中后4个最大的数 返回List的形式