Time waits for no one. Treasure every moment you have.
NumPy 简介
什么是 NumPy
NumPy(Numerical Python)是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
NumPy 是一个运行速度非常快的数学库,主要用于数组计算,包含:
- 一个强大的N维数组对象 ndarray
- 广播功能函数
- 整合 C/C++/Fortran 代码的工具
- 线性代数、傅里叶变换、随机数生成等功能
NumPy 的应用
NumPy 通常与 SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用,这种组合广泛用于替代 MatLab(Matrix Laboratory),是一个强大的科学计算环境,有助于我们通过 Python 学习数据科学或者机器学习。
SciPy 是一个开源的 Python 算法库和数学工具包。
SciPy 包含的模块有最优化、线性代数、积分、插值、特殊函数、快速傅里叶变换、信号处理和图像处理、常微分方程求解和其他科学与工程中常用的计算。
Matplotlib 是 Python 编程语言及其数值数学扩展包 NumPy 的可视化操作界面。它为利用通用的图形用户界面工具包,如 Tkinter,wxPython,Qt 或 GTK+ 向应用程序嵌入式绘图提供了应用程序接口(API)。
NumPy 的安装
Python 官网上的发行版是不包含 NumPy 模块的。
安装 NumPy 的两种方式:
- 1.使用已有的发行版本
Python 发行版比如 Anaconda、Enthought Canopy、Python(x,y)、WinPython、Pyzo,它们包含了所有的关键包(包括 NumPy,SciPy,matplotlib,IPython,SymPy 以及 Python 核心自带的其它包)。
笔者是通过安装 Anaconda 的方式,可参考文章「Anaconda新手入门」。 - 2.使用 pip 安装
安装 NumPy 最简单的方法就是使用 pip 工具:
pip3 install --user numpy scipy matplotlib
--user 选项可以设置只安装在当前的用户下,而不是写入到系统目录。
默认情况使用国外线路,但国外太慢,建议使用清华的镜像来安装:
pip3 install numpy scipy matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
测试是否安装成功(先使用 python
命令进入交互式模式):
>>> import numpy as np
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
NumPy 语法
好记性不如烂笔头,总结语法(几乎涵盖所有的知识点),以便随时翻阅复习。
花几个小时学习下面的语法内容,你就可以熟练使用 NumPy。
1.numpy.ndarray的存取
1)保存numpy.ndarray数组到文件中
语法:
numpy.save(file, input)
1)file可以是文件或文件名,如果是一个文件对象,文件名不会发生改变,并且文件可以不是.npy结尾。
如果是一个文件名,若该文件不是以.npy结尾,那么.npy会被自动附加到文件后缀。
2)读取文件为numpy.ndarray数组
语法:
input = numpy.load(file)
1)同样file可以是文件或文件名,如果是一个文件名,.npy后缀不能省略(也可以是.txt)。
代码示例:
import numpy
# 1)存取一条数据
a = numpy.array([1, 2, 3])
print(type(a), a)
numpy.save('./file/test', a) # 若该文件不是以.npy结尾,那么.npy会被自动附加到文件后缀
b = numpy.load('./file/test.npy')
print(type(b), b)
print("----------")
# 2)存取多条数据
with open('./file/yun.npy', 'wb') as f:
numpy.save(f, numpy.array([1, 2]))
numpy.save(f, numpy.array([3, 4]))
with open('./file/yun.npy', 'rb') as f:
a = numpy.load(f)
b = numpy.load(f)
print(a, b)
运行结果:
<class 'numpy.ndarray'> [1 2 3]
<class 'numpy.ndarray'> [1 2 3]
----------
[1 2] [3 4]
2.numpy.ndarray的数据类型
1)包括numpy.bool_、numpy.int8、numpy.int64、numpy.float32、numpy.float64等等。
2)可以通过dtype属性指定数据类型。
代码示例:
a = numpy.array([1]) # 如果是整形,默认为numpy.int64
b = numpy.array([1.]) # 如果是浮点型,默认为numpy.float64
c = numpy.array([1.], dtype=numpy.float32) # 通过dtype属性指定numpy.float32
d = numpy.array([True, False, False]) # numpy.bool_
print(type(a[0]), type(b[0]), type(c[0]), type(d[0]))
print(a.dtype, b.dtype, c.dtype, d.dtype)
运行结果:
<class 'numpy.int64'> <class 'numpy.float64'> <class 'numpy.float32'> <class 'numpy.bool_'>
int64 float64 float32 bool
3.numpy.ndarray的相关属性
.ndim 秩,即维度的数量或轴的数量
.shape 数组的维度/形状
.dtype 元素类型
.size 元素总个数
.itemsize 每个元素的大小,以字节为单位。比如int64大小为8个字节
代码示例:
a = numpy.array([[2, 3], [3, 4], [5, 6]])
print(a.shape) # 数组的形状/数组的维度
print(a.ndim) # 秩,即维度的数量或轴的数量
print(a.dtype) # 元素类型
print(a.size) # 元素总个数
print(a.itemsize) # 每个元素的大小,以字节为单位。比如int64大小为8个字节
运行结果:
(3, 2)
2
int64
6
8
4.创建numpy.ndarray
构造特殊矩阵:
1)全0矩阵、全1矩阵和空矩阵
numpy.zeros(shape, dtype)
numpy.ones(shape, dtype)
numpy.empty(shape, dtype)
1.创建一个指定形状、数据类型的数组,默认dtype=numpy.float64。
2.empty比zeros和ones的生成速度快,它的元素是空的(没有实际意义)。
2)单位矩阵E:numpy.eye(N, M=None)
N代表行数;M代表列数,若M=None,则默认M=N。
3)对角(diagonal)阵:numpy.diag(v, k=0)
v只能是二维或一维数组。
默认k=0,表示主对角线;k>0表示主对角线以上,k<0表示主对角线以下。
1.如果v是一个二维数组,则返回其第k条对角线的副本。
2.如果v是一个一维数组,则返回一个v位于第k条对角线的二维数组。
4)下三角(Lower triangle)矩阵:numpy.tril(m, k=0)
返回一个数组m的下三角副本,即第k条对角线以上的元素为零。
默认k=0,表示主对角线;k>0表示主对角线以上,k<0表示主对角线以下。
5)上三角(Upper triangle)矩阵:numpy.triu(m, k=0)
返回一个数组m的上三角副本,即第k条对角线以下的元素为零。
默认k=0,表示主对角线;k>0表示主对角线以上,k<0表示主对角线以下。
代码示例:
# 构造特殊矩阵:
print("==全0矩阵、全1矩阵和空矩阵==")
# 1)zeros()、ones()、empty()
# 默认元素类型都是float64类型,可以使用dtype属性指定元素类型
# empty相比zeros和ones,生成的速度快,因为empty的元素是空的没有实际意义。
a = numpy.zeros((1, 3)) # 全0矩阵
b = numpy.ones((1, 3)) # 全1矩阵
c = numpy.empty((1, 3), dtype=numpy.int8) # 空矩阵
print(a, a.dtype) # numpy.float64
print(b, b.dtype) # numpy.float64
print(c, c.dtype) # numpy.int8
print("==单位矩阵E==")
# 2)单位矩阵E:eye(N, M=None)
# N代表行数;M代表列数,若M=None,则默认M=N。
print(numpy.eye(3, 2))
print(numpy.eye(3)) # M=None,则默认M=N
print("==对角(diagonal)阵==")
# 3)对角(diagonal)阵: numpy.diag(v, k=0)
# v只能是二维或一维数组。
# 3.1如果v是一个二维数组,则返回其第k条对角线的副本。
v = numpy.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(numpy.diag(v)) # 默认k=0,表示主对角线
print(numpy.diag(v, k=1)) # k>0,表示主对角线上面第1条
print(numpy.diag(v, k=-2)) # k<0,表示主对角线下面第2条
# 3.2如果v是一个一维数组,则返回一个v位于第k条对角线的二维数组。
v = numpy.array([1, 2, 3])
print(numpy.diag(v, k=0))
print(numpy.diag(v, k=1))
print(numpy.diag(v, k=-1))
print("==下三角矩阵==")
# 4)下三角矩阵:numpy.tril(m, k=0)
# 返回一个数组m的下三角副本,即第k条对角线以上的元素为零。
a = numpy.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(numpy.tril(a, k=0)) # 默认k=0,表示主对角线
print(numpy.tril(a, k=1)) # k>0,表示主对角线上面第1条
print(numpy.tril(a, k=-1)) # k<0,表示主对角线下面第1条
print("==上三角矩阵==")
# 5)上三角矩阵:numpy.triu(m, k=0)
# 返回一个数组m的上三角副本,即第k条对角线以下的元素为零。
a = numpy.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(numpy.triu(a, k=0)) # 默认k=0,表示主对角线
print(numpy.triu(a, k=1)) # k>0,表示主对角线上面第1条
print(numpy.triu(a, k=-1)) # k<0,表示主对角线下面第1条
运行结果:
==全0矩阵、全1矩阵和空矩阵==
[[0. 0. 0.]] float64
[[1. 1. 1.]] float64
[[0 0 0]] int8
==单位矩阵E==
[[1. 0.]
[0. 1.]
[0. 0.]]
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
==对角(diagonal)阵==
[1 5 9]
[2 6]
[7]
[[1 0 0]
[0 2 0]
[0 0 3]]
[[0 1 0 0]
[0 0 2 0]
[0 0 0 3]
[0 0 0 0]]
[[0 0 0 0]
[1 0 0 0]
[0 2 0 0]
[0 0 3 0]]
==下三角矩阵==
[[ 1 0 0 0]
[ 5 6 0 0]
[ 9 10 11 0]]
[[ 1 2 0 0]
[ 5 6 7 0]
[ 9 10 11 12]]
[[ 0 0 0 0]
[ 5 0 0 0]
[ 9 10 0 0]]
==上三角矩阵==
[[ 1 2 3 4]
[ 0 6 7 8]
[ 0 0 11 12]]
[[ 0 2 3 4]
[ 0 0 7 8]
[ 0 0 0 12]]
[[ 1 2 3 4]
[ 5 6 7 8]
[ 0 10 11 12]]
5.从已有的数组创建numpy.ndarray
包括:
numpy.array(p_object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
numpy.asarray(a, dtype=None, order=None)
区别:
1)array中有copy属性,copy=True(默认)属于深拷贝,copy=False属于浅拷贝。
2)而asarray没有copy属性,都属于浅拷贝。
代码示例:
x = [1, 2, 3]
a = numpy.array(x, copy=True) # 深拷贝
b = numpy.asarray(x) # 浅拷贝
print(type(a), type(b))
print(a, b)
print('----------')
x = (1, 2, 3)
a = numpy.array(x, copy=False) # 浅拷贝
b = numpy.asarray(x) # 浅拷贝
print(type(a), type(b))
print(a, b)
print('----------')
x = numpy.array([(1, 2, 3), (4, 5)])
a = numpy.array(x) # 默认copy=True,深拷贝
b = numpy.asarray(x) # 浅拷贝
x[0] = (1, 2) # 改变x的值,浅拷贝会跟着改变,而深拷贝不会
print(type(a), type(b))
print(x, a, b) # x变了,b也跟着变了
运行结果:
<class 'numpy.ndarray'> <class 'numpy.ndarray'>
[1 2 3] [1 2 3]
----------
<class 'numpy.ndarray'> <class 'numpy.ndarray'>
[1 2 3] [1 2 3]
----------
<class 'numpy.ndarray'> <class 'numpy.ndarray'>
[(1, 2) (4, 5)] [(1, 2, 3) (4, 5)] [(1, 2) (4, 5)]
6.从数值范围创建numpy.ndarray
语法:
numpy.arange([start,] stop[, step,], dtype=None)
1)默认起始索引start=0,默认步长step=1。stop必须指定。
2)含前不含后,范围[start, stop)。
代码示例:
# 从半开区间[start, end)按步长step进行取值
a = numpy.arange(10) # 默认start=0,end=10,默认step=1
b = numpy.arange(-3, 6) # start=-3,end=6,默认step=1
c = numpy.arange(1, 9, 2) # start=1,end=9,默认step=2
print(a)
print(b)
print(c)
运行结果:
[0 1 2 3 4 5 6 7 8 9]
[-3 -2 -1 0 1 2 3 4 5]
[1 3 5 7]
7.使用input.astype(dtype=)转换数据类型
代码示例:
a = numpy.array([1, 2]) # 如果是整形,默认是numpy.int64
b = numpy.array([1, 2], dtype=numpy.int8) # 指定为numpy.int8
c = a.astype(dtype=numpy.float64) # 转换为numpy.float64
d = c.astype(dtype=a.dtype) # 转换为numpy.int64
print(a.dtype) # int64
print(b.dtype) # int8
print(c.dtype) # float64
print(d.dtype) # int64
运行结果:
int64
int8
float64
int64
8.numpy.ndarray的浅拷贝和深拷贝
1)浅拷贝:y=numpy.array(x, copy=False)或直接赋值y=x
对于浅拷贝,改变x、y中任一个,另一个也跟着变化
2)深拷贝:y=numpy.array(x, copy=True)或y=numpy.copy(x)或y=x.copy()
代码示例:
print("===浅拷贝===")
# 浅拷贝:改变x、y中任一个,另一个也跟着变化
x = numpy.array([1, 1])
y = numpy.array(x, copy=False) # copy=False,是浅拷贝
y[0] = 2
print(x, y)
print("---")
x = numpy.array([1, 1])
y = x # 直接赋值,是浅拷贝
y[0] = 2
print(x, y)
print("===深拷贝===")
# 深拷贝
x = numpy.array([1, 1])
y = numpy.array(x) # 默认copy=True,是深拷贝
y[0] = 2
print(x, y)
print("---")
x = numpy.array([1, 1])
y = numpy.array(x, copy=True) # copy=True,是深拷贝
y[0] = 2
print(x, y)
print("---")
x = numpy.array([1, 1])
y = numpy.copy(x) # 与x.copy()等价,是深拷贝
y[0] = 2
print(x, y)
print("---")
x = numpy.array([1, 1])
y = x.copy() # 与numpy.copy(x)等价,是深拷贝
y[0] = 2
print(x, y)
运行结果:
===浅拷贝===
[2 1] [2 1]
---
[2 1] [2 1]
===深拷贝===
[1 1] [2 1]
---
[1 1] [2 1]
---
[1 1] [2 1]
---
[1 1] [2 1]
9.numpy.tile(input, reps)复制函数
示例:
output=numpy.tile(input, (num1, num2, num3))
沿axis=0轴复制num1倍,沿axis=1轴复制num2倍,沿axis=2轴复制num3倍。
代码示例:
# 一维
a = numpy.array([1, 2])
print(numpy.tile(a, 2)) # 沿axis=0方向复制,变为原来的2倍
print(numpy.tile(a, (3,))) # 沿axis=0方向复制,变为原来的2倍
print("----------")
# 二维
a = numpy.array([[1, 2],
[3, 4]])
print(a)
print(numpy.tile(a, (2, 1))) # 沿axis=0复制变成原来的2倍
print(numpy.tile(a, (1, 3))) # 沿axis=1复制变为原来的3倍
print(numpy.tile(a, (2, 3))) # 沿axis=0复制变成原来的2倍,沿axis=1复制变为原来的3倍
print("----------")
# 三维
a = numpy.arange(24).reshape(3, 2, 4)
b = numpy.tile(a, (2, 2, 2))
print(a.shape, b.shape)
print(a)
print(b) # 沿axis=0变为2倍,沿axis=1变为2倍,沿axis=2变为2倍
运行结果:
[1 2 1 2]
[1 2 1 2 1 2]
----------
[[1 2]
[3 4]]
[[1 2]
[3 4]
[1 2]
[3 4]]
[[1 2 1 2 1 2]
[3 4 3 4 3 4]]
[[1 2 1 2 1 2]
[3 4 3 4 3 4]
[1 2 1 2 1 2]
[3 4 3 4 3 4]]
----------
(3, 2, 4) (6, 4, 8)
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]
[[16 17 18 19]
[20 21 22 23]]]
[[[ 0 1 2 3 0 1 2 3]
[ 4 5 6 7 4 5 6 7]
[ 0 1 2 3 0 1 2 3]
[ 4 5 6 7 4 5 6 7]]
[[ 8 9 10 11 8 9 10 11]
[12 13 14 15 12 13 14 15]
[ 8 9 10 11 8 9 10 11]
[12 13 14 15 12 13 14 15]]
[[16 17 18 19 16 17 18 19]
[20 21 22 23 20 21 22 23]
[16 17 18 19 16 17 18 19]
[20 21 22 23 20 21 22 23]]
[[ 0 1 2 3 0 1 2 3]
[ 4 5 6 7 4 5 6 7]
[ 0 1 2 3 0 1 2 3]
[ 4 5 6 7 4 5 6 7]]
[[ 8 9 10 11 8 9 10 11]
[12 13 14 15 12 13 14 15]
[ 8 9 10 11 8 9 10 11]
[12 13 14 15 12 13 14 15]]
[[16 17 18 19 16 17 18 19]
[20 21 22 23 20 21 22 23]
[16 17 18 19 16 17 18 19]
[20 21 22 23 20 21 22 23]]]
10.numpy.ndarray的升维和降维
1)升维
示例:若a的形状是(m, n),
a[:, None]变成(m, 1, n)
a[numpy.newaxis, :]变成(1, m, n)
a[None, :, numpy.newaxis]变成(1, m, 1, n)
2)降维
2.1)numpy.squeeze(a, axis=None)
axis表示对指定的维度进行压缩降维。默认axis=None,表示对所有维度进行压缩降维。
该操作只对长度为1的维度才有压缩降维的效果。
axis=None,对所有维度中长度为1的维度进行压缩降维;
axis=m,对指定维度(该维度长度必须为1,否则报错)进行压缩降维。
axis=(m, n, ...),对指定多个维度进行压缩降维。
2.2)ravel()和flatten()扁平化
a.flatten():扁平化操作,返回一个一维数组。
numpy.ravel(a)或a.ravel():扁平化操作,返回一个一维数组。
flatten和ravel的区别:
1.flatten是返回copy副本;
2.而ravel,如果没有必要,不会产生副本,而是返回view试图。
代码示例:
print("==升维==")
# 升维
x1 = numpy.arange(10).reshape(2, 5) # (2, 5)
x2 = x1[:, numpy.newaxis] # (2, 1, 5)
x3 = x1[None, :] # (1, 2, 5)
x4 = x1[numpy.newaxis, :, None] # (1, 2, 1, 5)
print(x1.shape, x2.shape, x3.shape, x4.shape)
print("==降维==")
# 1)numpy.squeeze(a, axis=None)
# axis表示对指定的维度进行压缩降维。默认axis=None,表示对所有维度进行压缩降维。
# 该操作只对长度为1的维度才有压缩降维的效果。
a = numpy.array([[[[1],
[2],
[3]]]])
print(a.shape) # (1, 1, 3, 1)
print(numpy.squeeze(a).shape) # (3, ) 默认axis=None,对所有维度进行压缩。
print(numpy.squeeze(a, axis=0).shape) # (1, 3, 1)
# 对于长度不是1的维度,不能进行压缩降维操作,否则出错。
# ValueError: cannot select an axis to squeeze out which has size not equal to one
# print(numpy.squeeze(a, axis=1).shape)
print(numpy.squeeze(a, axis=3).shape) # (1, 1, 3)
# 同时对多个维度进行压缩降维
print(numpy.squeeze(a, axis=(0, 1)).shape) # (3, 1)
print(numpy.squeeze(a, axis=(0, 1, 3)).shape) # (3,)
print("----------")
# 2)ravel()和flatten()扁平化
x1 = numpy.arange(6).reshape(1, 2, 1, 3)
print(x1.shape)
# ravel()和flatten()都是扁平化操作,返回一个一维数组。
x2 = x1.flatten()
x3 = numpy.ravel(x1) # 或 x2 = x1.ravel()
print(x2, x2.shape)
print(x3, x3.shape)
# flatten返回一个copy副本,改变x2,x1不会变化。
x2[0] = 9
print(x2, x1)
# ravel在这里返回一个view试图,改变x3,x1也跟着变化。
x3[0] = 9
print(x3, x1)
运行结果:
==升维==
(2, 5) (2, 1, 5) (1, 2, 5) (1, 2, 1, 5)
==降维==
(1, 1, 3, 1)
(3,)
(1, 3, 1)
(1, 1, 3)
(3, 1)
(3,)
----------
(1, 2, 1, 3)
[0 1 2 3 4 5] (6,)
[0 1 2 3 4 5] (6,)
[9 1 2 3 4 5] [[[[0 1 2]]
[[3 4 5]]]]
[9 1 2 3 4 5] [[[[9 1 2]]
[[3 4 5]]]]
11.numpy.ndarray的运算
1)矩阵乘法/叉乘的三种方式:
a @ b
a.dot(b) 或 numpy.dot(a, b)
numpy.matmul(a, b)
形状:(m, n) @ (n, l) = (m, l)
代码示例:
a = numpy.array([[1, 2], [3, 4]])
b = numpy.array([[6, 7], [8, 9]])
# 转换为布尔数组
print(a > b)
print(a > 2.5)
print("----------")
# 基本运算
print(a + b)
print(a - b)
print(3 * a)
print(a * b) # 点乘,对应位置相乘
print(a / 2)
print(a / b) # 点除,对应位置相除
print("----------")
# 矩阵乘法/叉乘
# 三种方式:a @ b、a.dot(b)或numpy.dot(a, b)、numpy.matmul(a, b)
a = numpy.array([[1, 1, 1],
[2, 2, 2]])
b = numpy.array([[2, 2],
[3, 3],
[4, 4]])
res1 = a @ b
res2 = a.dot(b)
res3 = numpy.dot(a, b)
res4 = numpy.matmul(a, b)
print(f"矩阵乘法维度: {a.shape} @ {b.shape} = {res1.shape}")
print(res1)
print(res2)
print(res3)
print(res4)
运行结果:
[[False False]
[False False]]
[[False False]
[ True True]]
----------
[[ 7 9]
[11 13]]
[[-5 -5]
[-5 -5]]
[[ 3 6]
[ 9 12]]
[[ 6 14]
[24 36]]
[[0.5 1. ]
[1.5 2. ]]
[[0.16666667 0.28571429]
[0.375 0.44444444]]
----------
矩阵乘法维度: (2, 3) @ (3, 2) = (2, 2)
[[ 9 9]
[18 18]]
[[ 9 9]
[18 18]]
[[ 9 9]
[18 18]]
[[ 9 9]
[18 18]]
12.numpy中的随机数
1)numpy.random.rand(*dn)均匀分布
表示从区间[0, 1)的均匀分布中抽取的一组随机数。
2)numpy.random.randn(*dn)标准正太分布
表示从均值为0方差为1的标准正太分布中抽取的一组随机数。
3)numpy.random.random(size)或numpy.random.random_sample(size)
表示从区间[0, 1)中随机抽取size的随机数。
4)numpy.random.randint(low, [high, size, dtype])
表示从半开区间[low, high)中随机抽取size的随机数。
若higt=None(默认),则表示从半开区间[0, low)中抽取。
默认size=None,返回一个int类型的数。否则就算size=1也是返回numpy.ndarray类型。
代码示例:
# 形如random.rand(2, 3), random.randn(2, 1, 3)
a = numpy.random.rand(2, 3)
b = numpy.random.randn(2, 3)
print(a.shape, a)
print(b.shape, b)
print("----------")
# random.random(size)和random.random_sample(size)等价
a = numpy.random.random(3)
b = numpy.random.random_sample(3)
c = numpy.random.random(size=[2, 3])
d = numpy.random.random_sample(size=[2, 3])
print(a.shape, a)
print(b.shape, b)
print(c.shape, c)
print(d.shape, d)
print("----------")
# numpy.random.randint(low[,high,size,dtype]):
# 随机获取半开区间[low, high)的随机数size个
# 若high=None,表示半开区间[0, low)
a = numpy.random.randint(1) # 没有指定size,[0, 1)中随机生成一个int随机数,即0
b = numpy.random.randint(1, 8) # 没有指定size,[1, 8)中随机生成一个int随机数
c = numpy.random.randint(1, 8, 1) # [1, 8)中抽取形状为(1,)的随机数
d = numpy.random.randint(1, 8, (3, 5)) # [1, 8)中抽取形状为(3, 5)的随机数
print(type(a), type(b), type(c), type(d))
print(a)
print(b)
print(c.shape, c)
print(d.shape, d)
运行结果:
(2, 3) [[0.17108017 0.14172812 0.60094525]
[0.17587946 0.38163881 0.26990619]]
(2, 3) [[ 0.20126965 -1.19856979 -0.09397926]
[-0.5350872 0.70604905 -0.39206149]]
----------
(3,) [0.47500327 0.26164558 0.24151724]
(3,) [0.64392958 0.78186747 0.67180093]
(2, 3) [[0.0019899 0.90901114 0.73034934]
[0.55435113 0.34141153 0.08330729]]
(2, 3) [[0.58217628 0.2928059 0.64746932]
[0.0272389 0.0283618 0.42395652]]
----------
<class 'int'> <class 'int'> <class 'numpy.ndarray'> <class 'numpy.ndarray'>
0
3
(1,) [2]
(3, 5) [[7 7 7 1 7]
[7 1 2 7 3]
[1 5 4 7 1]]
13.zip(seq1, seq2, ...)解包
list1,list2 = [1, 2], [3, 4]
tuple1, tuple2 = (5, 6), (7, 8)
for e in zip(list1, list2, tuple1, tuple2):
print(e)
print("----------")
xs = numpy.array([1, 2, 3])
ys = numpy.array([3.7, 4.4, 5.8])
for x, y in zip(xs, ys):
print(x, y)
print("----------")
data = ([5, 6, 7], [8, 9, 10])
for e in zip(*data):
print(e)
print("----------")
data = numpy.array([[1, 2], [3, 4]])
for e in zip(*data):
print(e)
运行结果:
(1, 3, 5, 7)
(2, 4, 6, 8)
----------
1 3.7
2 4.4
3 5.8
----------
(5, 8)
(6, 9)
(7, 10)
----------
(1, 3)
(2, 4)
14.numpy.linalg模块
1)矩阵求逆:numpy.linalg.inv(a)
矩阵乘法:A乘以"A的逆"的结果是"单位矩阵E"
2)求方正的行列式:numpy.linalg.det(a)
注意:只有"方正"才有行列式
3)求特征值和特征向量:λ, x = numpy.linalg.eig(a)
4)奇异值分解:U, ∑, V* = numpy.linalg.svd(a)
公式:M=U∑V*,V*是V的共轭转置。
形状:若a是m*n,则U是m*m,∑是m*n的对角阵,V*是n*n。
代码示例:
# 1)矩阵求逆:numpy.linalg.inv(a)
a = numpy.array([[1, 2],
[3, 4]])
a_inverse = numpy.linalg.inv(a)
# 矩阵乘法:A乘以"A的逆"的结果是"单位矩阵E"
print(a.dot(a_inverse))
print(a @ a_inverse)
print(numpy.matmul(a, a_inverse))
print("----------")
# 2)求方正的行列式:numpy.linalg.det(a)
# 注意:只有"方正"才有行列式
a_det = numpy.linalg.det(a)
print(a_det) # 1*4-2*3=-2
print("----------")
# 3)求特征值和特征向量:λ, x = numpy.linalg.eig(a)
λ, x = numpy.linalg.eig(a)
print("特征值:", λ)
print("特征向量:", x)
print("----------")
# 4)奇异值分解:U, ∑, V* = numpy.linalg.svd(a)
a = numpy.array([[1, 2],
[3, 4],
[5, 6]])
U, sigma, V_T = numpy.linalg.svd(a)
# 形状:若a是m*n,则U是m*m,∑是m*n的对角阵,V*是n*n。
print(a.shape, U.shape, sigma.shape, V_T.shape)
print(U)
print(sigma)
print(V_T)
运行结果:
[[1.00000000e+00 1.11022302e-16]
[0.00000000e+00 1.00000000e+00]]
[[1.00000000e+00 1.11022302e-16]
[0.00000000e+00 1.00000000e+00]]
[[1.00000000e+00 1.11022302e-16]
[0.00000000e+00 1.00000000e+00]]
----------
-2.0000000000000004
----------
特征值: [-0.37228132 5.37228132]
特征向量: [[-0.82456484 -0.41597356]
[ 0.56576746 -0.90937671]]
----------
(3, 2) (3, 3) (2,) (2, 2)
[[-0.2298477 0.88346102 0.40824829]
[-0.52474482 0.24078249 -0.81649658]
[-0.81964194 -0.40189603 0.40824829]]
[9.52551809 0.51430058]
[[-0.61962948 -0.78489445]
[-0.78489445 0.61962948]]
15.numpy.ndarray的转置和换轴
1)转置
示例:b = a.T
2)轴变换
1)换任意多个轴:transpose
2)互换两个轴:swapaxes
代码示例:
# 转置
a = numpy.arange(8).reshape(2, 4)
b = a.T
print(a.shape)
print(b.shape)
print('----------')
# 轴变换
# 1)换任意多个轴:transpose
a = numpy.arange(24).reshape(3, 2, 4)
b = numpy.transpose(a, (1, 2, 0))
c = a.transpose((1, 2, 0))
print(a.shape)
print(b.shape)
print(c.shape)
print('----------')
# 2)互相两个轴:swapaxes
a = numpy.arange(24).reshape(3, 2, 4)
b = numpy.swapaxes(a, 2, 0)
c = a.swapaxes(2, 0)
print(a.shape)
print(b.shape)
print(c.shape)
运行结果:
(2, 4)
(4, 2)
----------
(3, 2, 4)
(2, 4, 3)
(2, 4, 3)
----------
(3, 2, 4)
(4, 2, 3)
(4, 2, 3)
16.numpy的统计函数
包括:
和:numpy.sum(a, axis=None)
最小值:numpy.amin(a, axis=None)或numpy.min(a, axis=None)
最大值:numpy.amax(a, axis=None)或numpy.max(a, axis=None)
最大值-最小值:numpy.ptp(a, axis=None)
百分位数:numpy.percentile(a, q, axis=None)
1)百分位数q取值在[0, 100]之间
2)第一个数的百分位数是0,最后一个数的百位数是100
中位数/中值:numpy.median(a, axis=None)
平均值:numpy.mean(a, axis=None)
加权平均值:numpy.average(a, axis=None, weights=None)
avg = sum(a * weights) / sum(weights)
示例:数组a=[1,2,3,4],权重weights=[4,3,2,1],
则加权平均值=(1*4+2*3+3*2+4*1)/(4+3+2+1)
注意:默认weights=None,表示各权重值均为1,此时与mean函数等价。
方差:numpy.var(a, axis=None)
var = mean((x - x.mean())**2)
标准差:numpy.std(a, axis=None)
std = sqrt(mean((x - x.mean())**2))
1)axis表示沿着哪个轴做计算。默认axis=None,表示先flatten展开再计算,结果始终是一个数。
2)若输入a的形状为(AxBxC),则:
axis=0的输出形状为(BxC),
axis=1的输出形状为(AxC),
axis=2的输出形状为(AxB),
axis=None的计算结果始终是一个数。
3)min是amin的别名,max是amax的别名,它们分别代表同一个函数。
4)average是加权平均,当weights=None时,表示各权重值均为1,此时与mean函数等价。
代码示例:
print("==输出形状==")
a = numpy.arange(60).reshape(3, 4, 5)
print(a.shape) # (3, 4, 5)
# 输入a的形状为(AxBxC),则axis=0的输出形状为(BxC)
print(a.sum(axis=0).shape) # (4, 5)
print(a.min(axis=0).shape) # (4, 5)
print(a.max(axis=0).shape) # (4, 5)
print(a.mean(axis=0).shape) # (4, 5)
# 输入a的形状为(AxBxC),则axis=1的输出形状为(AxC)
print(numpy.amin(a, axis=1).shape) # (3, 5)
print(numpy.amax(a, axis=1).shape) # (3, 5)
print(numpy.percentile(a, 0, axis=1).shape) # (3, 5)
print(numpy.median(a, axis=1).shape) # (3, 5)
# 输入a的形状为(AxBxC),则axis=2的输出形状为(AxB)
print(numpy.mean(a, axis=2).shape) # (3, 4)
print(numpy.average(a, axis=2).shape) # (3, 4)
print(numpy.var(a, axis=2).shape) # (3, 4)
print(numpy.std(a, axis=2).shape) # (3, 4)
# 默认axis=None,表示先flatten扁平展开再计算,计算结果始终是一个数。
print(a.sum(), a.min(), a.ptp(),
numpy.percentile(a, 100),
numpy.average(a),
a.var())
print("-----我是华丽的分割线-----")
a = numpy.array([[3, 7, 5],
[8, 2, 1],
[6, 4, 9]])
print("==求和==")
# 求和
print(numpy.sum(a))
print(numpy.sum(a, axis=0))
print(numpy.sum(a, axis=1))
print("==最小值==")
# 最小值
print(numpy.amin(a)) # 1,默认axis=None
print(numpy.min(a)) # 1,min是amin的别名,代表同一个函数
print(numpy.amin(a, axis=0)) # [3 2 1]
print(numpy.amin(a, axis=1)) # [3, 1, 4]
print("==最大值==")
# 最大值
print(numpy.amax(a)) # 9,默认axis=None
print(numpy.max(a)) # 9,max是amax的别名,代表同一个函数
print(numpy.amax(a, axis=0)) # [8, 7, 9]
print(numpy.amax(a, axis=1)) # [7, 8, 9]
print("==最大值-最小值==")
# 最大值-最小值
print(numpy.ptp(a)) # 8,max-min=9-1=8
print("==百分位数==")
# 百分位数: percentile(a, q, axis=None)
# 百分位数q取值在[0, 100]之间,第一个数的q是0,最后一个数的q是100
# 总共9个数,8等分,每一等分占100/8=12.5,第二个数的百分位数是12.5
print(numpy.percentile(a, 0))
print(numpy.percentile(a, 1.25))
print(numpy.percentile(a, 12.5))
print(numpy.percentile(a, 50))
print(numpy.percentile(a, 87.5))
print(numpy.percentile(a, 100))
print("==中位数/中值==")
# 中位数/中值
print(numpy.median(a, axis=None))
print(numpy.median(a, axis=0))
print(numpy.median(a, axis=1))
print("==平均值==")
a = numpy.array([[1, 2],
[4, 5]])
print(numpy.mean(a, axis=None)) # (1+2+4+5)/4=3
print(numpy.mean(a, axis=0)) # (4+1)/2=2.5,(2+5)/2=3.5
print("==加权平均值==")
# avg = sum(a * weights) / sum(weights)
a = numpy.array([[1, 2],
[4, 5]])
weights = numpy.array([[1, 2],
[3, 4]])
# (1*1+2*2+4*3+5*4)/(1+2+3+4)=37/10=3.7
print(numpy.average(a, axis=None, weights=weights))
# (1*1+4*3)/(1+3)=13/4=3.25,(2*2+5*4)/(2+4)=24/6=4
print(numpy.average(a, axis=0, weights=weights))
# (1*1+2*2)/(1+2)=5/3=1.667,(4*3+5*4)/(3+4)=32/7=4.57
print(numpy.average(a, axis=1, weights=weights))
# weights=None时,表示各权重值为1,此时与mean等价。
print(numpy.average(a, weights=None))
print("==方差与标准差==")
# var = mean((x - x.mean())**2)
# std = sqrt(mean((x - x.mean())**2))
a = numpy.array([1, 2, 4, 5])
print(numpy.mean(a)) # 3
print(numpy.var(a)) # [(1-3)^2+(2-3)^2+(4-3)^2+(5-3)^2]/4=10/4=2.5
print(numpy.std(a)) # sqrt(2.5)=1.581
运行结果:
==输出形状==
(3, 4, 5)
(4, 5)
(4, 5)
(4, 5)
(4, 5)
(3, 5)
(3, 5)
(3, 5)
(3, 5)
(3, 4)
(3, 4)
(3, 4)
(3, 4)
1770 0 59 59.0 29.5 299.9166666666667
-----我是华丽的分割线-----
==求和==
45
[17 13 15]
[15 11 19]
==最小值==
1
1
[3 2 1]
[3 1 4]
==最大值==
9
9
[8 7 9]
[7 8 9]
==最大值-最小值==
8
==百分位数==
1.0
1.1
2.0
5.0
8.0
9.0
==中位数/中值==
5.0
[6. 4. 5.]
[5. 2. 6.]
==平均值==
3.0
[2.5 3.5]
==加权平均值==
3.7
[3.25 4. ]
[1.66666667 4.57142857]
3.0
==方差与标准差==
3.0
2.5
1.5811388300841898
17.numpy的排序、条件刷选函数
1)numpy.sort(a, axis=-1, kind=None, order=None)
返回数组"从小到大"排序的副本。
1.axis表示沿着哪个轴做排序,默认axis=-1。若axis=None,表示先flatten展开再排序。
2.kind指定排序类型,默认为"quicksort",包括:
'quicksort'(快速排序)、
'mergesort'(归并排序)、
'heapsort'(堆排序)
3.order: 如果数组包含字段,则是要排序的字段。
2)numpy.argsort(a, axis=-1, kind=None, order=None)
与numpy.sort()类似,返回数组"从小到大"排序的索引值。
3)numpy.lexsort(keys, axis=None)
返回数组"按多个序列-->从右到左"、"从小到大"排序的索引值。
示例:
ind = numpy.lexsort((a, b))
其中keys=(a, b),根据"从右到左"原则,
即先按b进行排序,若b排序的结果一致则再按a进行排序。
4)numpy.argmax(a, axis=None)和numpy.argmin(a, axis=None)
沿指定轴返回最大、最小元素的索引。默认axis=None,表示先flatten展开再获取。
5)numpy.nonzero(a):返回数组中非零元素的索引。
6)numpy.where(condition[, x, y])函数的两种用法:
1.numpy.where(condition):输出满足条件的索引
2.numpy.where(condition, x, y):满足条件替换为x,不满足条件替换为y
7)numpy.extract(condition, x):提取满足条件的元素
代码示例:
print("===numpy.sort(a, axis=-1, kind=None, order=None)==")
# 返回数组"从小到大"排序的副本。
a = numpy.array([[3, 7],
[9, 1]])
print(numpy.sort(a, axis=None)) # 先flatten展开再排序
print(numpy.sort(a, axis=0))
print(numpy.sort(a, axis=-2))
print(numpy.sort(a, axis=1))
print(numpy.sort(a, axis=-1))
print(numpy.sort(a)) # 默认axis=-1
# 在 sort 函数中排序字段
dt = numpy.dtype([('name', 'S10'), ('age', int)])
a = numpy.array([("li", 21), ("yun", 15), ("fei", 18), ("fancle", 22)], dtype=dt)
print(numpy.sort(a, order='name')) # 按name字段进行排序
print("===numpy.argsort(a, axis=-1, kind=None, order=None)==")
# 与numpy.sort()类似,返回数组"从小到大"排序的索引值。
a = numpy.array([[3, 7],
[9, 1]])
print(numpy.argsort(a, axis=None))
print(numpy.argsort(a, axis=0))
print(numpy.argsort(a)) # 默认axis=-1
x = numpy.array([3, 7, 2, 5, 8, 6, 9, 1, 4])
y = numpy.argsort(x)
for i in y:
print(x[i], end=" ")
print()
print("===numpy.lexsort(keys, axis=None)==")
# 返回数组"按多个序列-->从右到左"、"从小到大"排序的索引值。
a = ('an', 'an', 'am', 'am')
b = ('f.y.', 's.y.', 's.y.', 'f.y.')
# 先按b进行排序,0、3索引在前,1、2索引在后;
# 然后按a进行排序,索引3在0前,索引2在1前。
# 最终结果:[3 0 2 1]
print(numpy.lexsort((a, b))) # sort by b, then by a
# 先按a进行排序,2、3索引在前,0、1索引在后;
# 然后按b进行排序,索引3在2前,索引1在0前。
# 最后结果:[3 2 1 0]
print(numpy.lexsort((b, a))) # sort by a, then by b
print("===numpy.argmax(a, axis=None)和numpy.argmin(a, axis=None)==")
# 沿指定轴返回最大、最小元素的索引
a = numpy.array([[30, 40, 70],
[80, 20, 10],
[50, 90, 60]])
print(numpy.argmax(a)) # 默认axis=None
print(numpy.argmax(a, axis=0))
print(numpy.argmax(a, axis=1))
print(numpy.argmin(a)) # 默认axis=None
print(numpy.argmin(a, axis=0))
print(numpy.argmin(a, axis=1))
print("===numpy.nonzero(a)==")
# 返回数组中非零元素的索引
a = numpy.array([[30, 40, 0],
[0, 20, 10],
[50, 0, 60]])
print(numpy.nonzero(a))
print("===numpy.where(condition[, x, y])==")
# numpy.where(condition):输出满足条件的索引
# numpy.where(condition, x, y):满足条件替换为x,不满足条件替换为y
a = numpy.array([3, 4, 7, 8, 9, 2, 10])
b = numpy.array([[1, 2, 5, 7],
[3, 4, 9, 1]])
# 获取满足条件的索引
c = numpy.where(a % 2 == 0)
d = numpy.where(b % 2 == 1)
# 替换元素
e = numpy.where(a > 4, 1, 2)
print(c)
print(d)
print(e)
print("==numpy.extract(condition, x)==")
# 提取满足条件的元素
a = numpy.array([3, 4, 7, 8, 9, 2, 10])
condition = numpy.mod(a, 2) == 0 # a/2的余数是0,即刷选偶数
print(condition)
print(numpy.extract(condition, a))
运行结果:
===numpy.sort(a, axis=-1, kind=None, order=None)==
[1 3 7 9]
[[3 1]
[9 7]]
[[3 1]
[9 7]]
[[3 7]
[1 9]]
[[3 7]
[1 9]]
[[3 7]
[1 9]]
[(b'fancle', 22) (b'fei', 18) (b'li', 21) (b'yun', 15)]
===numpy.argsort(a, axis=-1, kind=None, order=None)==
[3 0 1 2]
[[0 1]
[1 0]]
[[0 1]
[1 0]]
1 2 3 4 5 6 7 8 9
===numpy.lexsort(keys, axis=None)==
[3 0 2 1]
[3 2 0 1]
===numpy.argmax(a, axis=None)和numpy.argmin(a, axis=None)==
7
[1 2 0]
[2 0 1]
5
[0 1 1]
[0 2 0]
===numpy.nonzero(a)==
(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 0, 2]))
===numpy.where(condition[, x, y])==
(array([1, 3, 5, 6]),)
(array([0, 0, 0, 1, 1, 1]), array([0, 2, 3, 0, 2, 3]))
[2 2 1 1 1 2 1]
==numpy.extract(condition, x)==
[False True False True False True True]
[ 4 8 2 10]
18.numpy.ndarray的切片和基本索引
ndarray对象的内容可以通过索引和切片来访问和修改,与Python中list的切片操作一样。
1)切片的两种操作方式:
1.通过内置的slice(start, stop, step)函数
2.通过冒号分隔切片参数 start:stop:step 来进行切片操作
2)冒号:的解释:
1.如果只放置一个参数,如[2],将返回与该索引相对应的单个元素。
2.如果为[2:],则表示从该索引开始,包括以后的所有项都被提取。
3.如果使用了两个参数,如[2:7],则提取两个索引(不包括停止索引)之间的项。
3)省略号...的解释:
1.使得选择元组的长度与数组的维度相同。
2.同时表示在这些维度上全部截取。
若...代表一维,等价于切片":",
若...代表二维,等价于切片":, :",
以此类推。
4)多维数组的切片、索引操作,遵循2条准则:
1.索引操作降维,切片操作不降维。
2.逗号","表示在下一个维度进行操作。
只要记住上面的2条准则,就很容易理解高维数组的切片、索引操作。
示例:假设a是一个二维数组。
1.a[m]:索引操作降维,所以结果是一维数组。
2.a[m, n]:先索引降一个维度,然后逗号","表示在下一个维度操作,
再次进行索引操作又降一个维度,所以结果是一个数。与a[m][n]结果一致。
3.a[m:n]:切片操作不降维,还是二维数组。
4.a[m, n:l]:先索引降一个维度,然后在下一个维度,进行切片操作不降维,
所以结果是一维数组。与a[m][n:l]结果一致。
5.a[1:, 1]:先切片不降维,然后在下一个维度,进行索引操作降维,所以结果是一维数组。
6.a[1:][1]:先切片不降维,然后对这个二维数组进行索引操作降低一个维度,所以结果是一维数组。
7.a[1:, 1:]:先切片不降维,然后在下一个维度,再次切片不降维,所以结果是二维数组。
8.a[1:][1:]:先切片不降维,然后对这个二维数组再次切片不降维,所以结果是二维数组。
代码示例:
print("==切片的两种操作方式==")
# 1)切片的两种操作方式
a = numpy.arange(10)
s = slice(2, 7, 2) # 从索引 2 开始到索引 7 停止,间隔为2
print(a[s])
b = a[2:7:2] # 从索引 2 开始到索引 7 停止,间隔为2
print(b)
print("==冒号:的解释==")
# 2)冒号:的解释
a = numpy.arange(10) # [0 1 2 3 4 5 6 7 8 9]
b = a[5]
print(b)
print(a[2:])
print(a[2:5]) # 不包括停止索引5所对应的项a[5]
print("==省略号...的解释==")
# 3)省略号...的解释:
# 1.使得选择元组的长度与数组的维度相同。
# 2.同时表示在这些维度上全部截取。
a = numpy.array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
# a是一个三维数组
print(a.shape) # (2, 2, 2)
# 1表示对最后一个维度进行索引操作,a是三维数组;
# ...使得选择元组的长度与a数组一致,所以...代表二维,等价于":, :"。
print(a[..., 1])
print(a[:, :, 1])
print("----------")
# 1、0分别表示对前两个维度进行索引操作,a是三维数组;
# ...使得选择元组的长度与a数组一致,所以...代表二维,等价于":"。
print(a[1, 0, ...])
print(a[1, 0, :])
print("----------")
# 1:表示对最后一个维度进行切片操作,a是三维数组;
# ...使得选择元组的长度与a数组一致,所以...代表二维,等价于":, :"。
print(a[..., 1:])
print(a[:, :, 1:])
print("==多维数组的切片、索引操作==")
# 4)多维数组的切片、索引操作,遵循2条准则:
# 1.索引操作降维,切片操作不降维。
# 2.逗号","表示在下一个维度进行操作。
a = numpy.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 索引操作降维,所以结果是一维数组。
print(a[0])
print("----------")
# 两次索引操作降低两个维度,所以结果是一个数。
# a[m, n]与a[m][n]结果一致。
print(a[1, 2])
print(a[1][2])
print("----------")
# a[m:n]切片操作不降维,结果是二维数组。
print(a[1:])
print("----------")
# 先索引降维,然后切片不降维,结果是一维数组。
# a[m, n:l]与a[m][n:l]等价。
print(a[1, 1:])
print(a[1][1:])
print("----------")
# 先切片不降维,然后在下一个维度,进行索引操作降维,所以结果是一维数组。
print(a[1:, 1])
# 先切片不降维,然后对这个二维数组进行索引操作降低一个维度,所以结果是一维数组。
print(a[1:][1])
# 先切片不降维,然后在下一个维度,再次切片不降维,所以结果是二维数组。
print(a[1:, 1:])
# 先切片不降维,然后对这个二维数组再次切片不降维,所以结果是二维数组。
print(a[1:][1:])
运行结果:
==切片的两种操作方式==
[2 4 6]
[2 4 6]
==冒号:的解释==
5
[2 3 4 5 6 7 8 9]
[2 3 4]
==省略号...的解释==
(2, 2, 2)
[[2 4]
[6 8]]
[[2 4]
[6 8]]
----------
[5 6]
[5 6]
----------
[[[2]
[4]]
[[6]
[8]]]
[[[2]
[4]]
[[6]
[8]]]
==多维数组的切片、索引操作==
[1 2 3]
----------
6
6
----------
[[4 5 6]
[7 8 9]]
----------
[5 6]
[5 6]
----------
[5 8]
[7 8 9]
[[5 6]
[8 9]]
[[7 8 9]]
19.numpy.ndarray的高级索引
高级索引(包括布尔索引、整数数组索引、花式索引)总是返回一个副本。
1)布尔索引
我们可以通过一个布尔数组来索引目标数组。
布尔索引通过布尔运算(如:比较运算符)来获取"符合条件的元素"的数组。
~ 是取补运算符。
2)整数数组索引
1.连续两个整数数组索引,且两整数数组的长度一致。
示例:获取数组x中(0,0),(1,1)和(2,0)位置处的元素。
y = x[[0,1,2], [0,1,0]]
# [x[0][0], x[1][1], x[2][0]]
2.连续两个整数数组索引,且两整数数组的长度不一致(但是可以广播)。
示例:获取数组x中(2,0),(1,1)和(3,0)位置处的元素。
y = x[[2,1,3], [0]]
# [x[2][0], x[1][0], x[3][0]]
3)花式索引: numpy.ix_()
1.传入单个索引数组,表示取对应下标的元素。
2.传入多个索引数组(要使用np.ix_)
示例:a[numpy.ix_([3, 0], [0, 1])]
# [[a[3][0], a[3][1]],
[a[0][0], a[0][1]]]
代码示例:
print("===ndarray的布尔索引===")
# 一维
x = numpy.array([7, 2, 3, 1, 4])
a = x > 3 # 得到布尔数组
print(a)
print(x[x > 3])
print(x[a])
print(x[numpy.array([True, False, False, False, True])])
print(x[~a]) # ~是取补运算符
print(x[x % 2 == 1])
print("----------")
# 二维
x = numpy.array([[1, 2], [3, 4], [4, 5], [7, 6], [8, 10]])
a = numpy.array([False, True, True, False, True])
print(x[a])
print("===ndarray的整数数组索引===")
a = numpy.array([[1, 2],
[4, 3],
[6, 5],
[7, 8],
[9, 10]])
# 1.连续两个整数数组索引,且两整数数组的长度一致。
# [a[3][0], a[2][1]]
print(a[[3, 2], [0, 1]])
# 2.连续两个整数数组索引,且两整数数组的长度不一致(但是可以广播)。
# [a[2][0], a[4][0]]
print(a[[2, 4], [0]])
# [a[3][0], a[3][1], a[3][0], a[3][1]]
print(a[[3], [0, 1, 0, 1]])
print("===ndarray的花式索引: numpy.ix_()===")
a = numpy.array([[1, 2],
[4, 3],
[6, 5],
[7, 8],
[9, 10]])
# 1.传入单个索引数组,表示取对应下标的元素。
# [a[3], a[2], a[4], a[2], a[0], a[3]]
print(a[[3, 2, 4, 2, 0, -2]])
# 2.传入多个索引数组(要使用np.ix_)
print(a[numpy.ix_([3, 0], [0, 1])])
运行结果:
===ndarray的布尔索引===
[ True False False False True]
[7 4]
[7 4]
[7 4]
[2 3 1]
[7 3 1]
----------
[[ 3 4]
[ 4 5]
[ 8 10]]
===ndarray的整数数组索引===
[7 5]
[6 9]
[7 8 7 8]
===ndarray的花式索引: numpy.ix_()===
[[ 7 8]
[ 6 5]
[ 9 10]
[ 6 5]
[ 1 2]
[ 7 8]]
[[7 8]
[1 2]]
20.numpy的广播(Broadcast)
广播(Broadcast)是numpy对不同shape的数组进行数值计算的方式。
当两个不同形状的数组进行运算时,会自动触发广播机制。
广播的规则:
1.让所有输入数组都向其中形状最长(秩最大)的数组看齐,形状不足通过加1补齐。
2.输出数组形状是输入数组形状的各个维度上的最大值。
3.输入数组某个维度上的长度,必须满足下面的条件才可运算,否则出错:
1)与输出数组对应维度上的长度相同;
2)或者该长度为1。
4.当输入数组的某个维度的长度为1时,沿着此维度运算时都用此维度上的第一组值。
简单理解:
1.对于两个数组,首先向秩最大的数组看齐(形状不足加1补齐);
2.能够运算的条件是要么对应维度的长度相等,要么其中一个长度为1。
代码示例:
a = numpy.array([1, 2, 3])
b = numpy.array([[4, 5, 6]])
print(a.shape, b.shape) # (3,) (1, 3)
# 首先向秩最大的数组看齐:由于a.shape=(3,),b.shape=(1, 3),
# 所以补齐a.shape=(1, 3),即得到[[1, 2, 3]]。
# 然后再进行加法运算:(1, 3)+(1, 3),
# 输出的shape=(1, 3),最终得到[[5, 7, 9]]
c = a + b
print(c.shape, c)
print("----------")
a = numpy.array([1, 2])
b = numpy.array([[3, 4],
[5, 6],
[7, 8]])
print(a.shape, b.shape)
# 首先向秩最大的数组看齐:由于a.shape=(2,),b.shape=(3, 2),
# 所以补齐a.shape=(1, 2),即得到[[1, 2]]。
# 然后在进行加法运算:(1, 2)+(3, 2),
# 因为1、3中有个是1,所以可以运算,输出的shape=(3, 2)
c = a + b
print(c.shape, c)
print("----------")
a = numpy.array([1, 2])
b = numpy.array([1, 2, 3, 4])
print(a.shape, b.shape)
# 由于a.shape=(2,),b.shape=(4,),2和4不相等且都不为1,所以不能运算。
# ValueError: operands could not be broadcast together with shapes (2,) (4,)
print(a + b)
运行结果:
(3,) (1, 3)
(1, 3) [[5 7 9]]
----------
(2,) (3, 2)
(3, 2) [[ 4 6]
[ 6 8]
[ 8 10]]
----------
(2,) (4,)
ValueError: operands could not be broadcast together with shapes (2,) (4,)
21.其他一些常用函数
1)等差数列numpy.linspace()和等比数列numpy.logspace():
1.等差数列
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
start 起始值
stop 终止值
num 元素个数
endpoint 是否包含stop值
2.等比数列
numpy.ogspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0)
start 起始值
stop 终止值
num 元素个数
endpoint 是否包含stop值
base 对数log的底数
2)numpy.random.seed(seed=)
当设置相同的随机种子seed时,随机生成的数据是一样的。
3)numpy.unique(ar, return_inverse=False, axis=None)
返回去重并按"从小到大"排序的副本。
1.axis表示沿哪个轴进行去重和排序操作。默认axis=None,表示先flatten展开。
2.默认return_inverse=False表示去重操作不可逆,直接返回去重并排序后的结果。
若return_inverse=True表示操作可逆,此时返回去重排序后的结果+原始数据的索引信息。
4)numpy.mod(x1, x2):取余
5)numpy.sqrt(x):开根号/取算术平方根
代码示例:
print("==等差数列numpy.linspace()==")
# 1.等差数列
# numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
# start 起始值
# stop 终止值
# num 元素个数
# endpoint 是否包含stop值
seq1 = numpy.linspace(1, 10, 10) # A10=10,A1=1;9=9d;d=1
seq2 = numpy.linspace(1, 10, 10, endpoint=False) # A11=10,A1=1;9=10d;d=0.9
seq3 = numpy.linspace(1, 10, 15, endpoint=False) # A16=10,A1=1;9=15d;d=0.6
print(seq1)
print(seq2)
print(seq3)
print("==等比数列numpy.logspace()==")
# 2.等比数列
# numpy.ogspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0)
# start 起始值
# stop 终止值
# num 元素个数
# endpoint 是否包含stop值
# base 对数log的底数
seq4 = numpy.logspace(1, 2, 5) # B5=10**2,B1=10**1;10**2/10**1 = q**4
seq5 = numpy.logspace(1, 2, 5, endpoint=False) # B6=10**2,B1=10**1; 10**2/10**1 = q**5
print(seq4)
print(seq5)
print("==numpy.random.seed(seed=)==")
# 随机种子
print(numpy.random.random((2, 3)))
print(numpy.random.random((2, 3)))
# 当设置相同的随机种子seed时,随机生成的数据是一样的。
numpy.random.seed(seed=2)
a = numpy.random.random((2, 3))
numpy.random.seed(seed=2)
b = numpy.random.random((2, 3))
print(a)
print(b)
print("==numpy.unique(ar, return_inverse=False, axis=None)==")
# 返回去重并按"从小到大"排序的副本。
# 1.axis表示沿哪个轴进行去重和排序操作。默认axis=None,表示先flatten展开。
# 2.默认return_inverse=False表示去重操作不可逆,直接返回去重并排序后的结果。
# 若return_inverse=True表示操作可逆,此时返回去重排序后的结果+原始数据的索引信息。
a = [5, 2, 3, 2, 5, 1, 4, 3]
# 先去重得到[5, 2, 3, 1, 4],然后"从小到大"排序得到[1, 2, 3, 4, 5]
print(numpy.unique(a))
# 返回去重并排序后的结果+原始数据的索引信息
print(numpy.unique(a, return_inverse=True))
# 通过返回的去重元素和原始索引信息,可还原原始数据:
res, inx = numpy.unique(a, return_inverse=True)
print(res[inx])
print("----------")
a = numpy.array([[5, 4, 4],
[2, 1, 1],
[2, 1, 1]])
print(numpy.unique(a)) # 默认axis=None,表示先flatten展开再去重
print(numpy.unique(a, axis=0)) # 沿axis=0轴进行去重然后从小到大排序
print(numpy.unique(a, axis=1)) # 沿axis=1轴进行去重然后从小到大排序
# 返回去重并排序后的结果+原始数据的索引信息
print(numpy.unique(a, return_inverse=True, axis=0))
# 通过返回的去重元素和原始索引信息,可还原原始数据:
res, inx = numpy.unique(a, return_inverse=True, axis=0)
print(res[inx])
print("==numpy.mod(x1, x2)==")
# 取余函数:numpy.mod(x1, x2)
print(5 / 3) # 求商
print(5 // 3) # 求商取整
print(5 % 3) # 求商取余
print(numpy.mod(5, 3)) # 取余
a = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(numpy.mod(a, 3)) # 取余
print("==numpy.sqrt(x)==")
# 开根号:numpy.sqrt(x)
a = numpy.array([1, 4, 9, 8])
print(numpy.sqrt(a))
print(numpy.sqrt(9))
运行结果:
==等差数列numpy.linspace()==
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[1. 1.9 2.8 3.7 4.6 5.5 6.4 7.3 8.2 9.1]
[1. 1.6 2.2 2.8 3.4 4. 4.6 5.2 5.8 6.4 7. 7.6 8.2 8.8 9.4]
==等比数列numpy.logspace()==
[ 10. 17.7827941 31.6227766 56.23413252 100. ]
[10. 15.84893192 25.11886432 39.81071706 63.09573445]
==numpy.random.seed(seed=)==
[[0.97549396 0.20169961 0.8668077 ]
[0.08854281 0.36743639 0.14457917]]
[[0.89343825 0.47691714 0.75071795]
[0.09057856 0.58833575 0.34731977]]
[[0.4359949 0.02592623 0.54966248]
[0.43532239 0.4203678 0.33033482]]
[[0.4359949 0.02592623 0.54966248]
[0.43532239 0.4203678 0.33033482]]
==numpy.unique(ar, return_inverse=False, axis=None)==
[1 2 3 4 5]
(array([1, 2, 3, 4, 5]), array([4, 1, 2, 1, 4, 0, 3, 2]))
[5 2 3 2 5 1 4 3]
----------
[1 2 4 5]
[[2 1 1]
[5 4 4]]
[[4 5]
[1 2]
[1 2]]
(array([[2, 1, 1],
[5, 4, 4]]), array([1, 0, 0]))
[[5 4 4]
[2 1 1]
[2 1 1]]
==numpy.mod(x1, x2)==
1.6666666666666667
1
2
2
[1 2 0 1 2 0 1 2 0]
==numpy.sqrt(x)==
[1. 2. 3. 2.82842712]
3.0
22.实战——计算两个向量的余弦相似度
余弦相似度:即通过计算两个向量的夹角余弦值来评估它们的相似度。
计算公式:cosine_similarity = (a·b)/(|a||b|)
代码示例:
# numpy中,a·b=a@(b.T);另外,|a|=sqrt(a@(a.T)),|b|=sqrt(b@(b.T))
a = numpy.array([8])
b = numpy.array([-1])
c = numpy.array([9])
cosine_ac = a.dot(c.T) / (numpy.sqrt(a.dot(a.T)) * numpy.sqrt(c.dot(c.T)))
cosine_bc = b.dot(c.T) / (numpy.sqrt(b.dot(b.T)) * numpy.sqrt(c.dot(c.T)))
print(cosine_ac)
print(cosine_bc)
print("--------")
a = numpy.array([10, 1])
b = numpy.array([-10, 1])
c = numpy.array([4, 3])
cosine_ac = a.dot(c.T) / (numpy.sqrt(a.dot(a.T)) * numpy.sqrt(c.dot(c.T)))
cosine_bc = b.dot(c.T) / (numpy.sqrt(b.dot(b.T)) * numpy.sqrt(c.dot(c.T)))
print(cosine_ac)
print(cosine_bc)
print("--------")
a = numpy.array([1, 2, 4])
b = numpy.array([4, 3, 4])
cosine_ab = a.dot(b.T) / (numpy.sqrt(a.dot(a.T)) * numpy.sqrt(b.dot(b.T)))
print(cosine_ab)
运行结果:
1.0
-1.0
--------
0.8557319835805907
-0.736327520755392
--------
0.8860776295682962
23.实战——高维数组的切片和索引
代码示例:
"""
多维数组的切片、索引操作,遵循2条准则:
1.索引操作降维,切片操作不降维。
2.逗号","表示在下一个维度进行操作
"""
# 做对下面的题目,numpy的切片和索引你就掌握了。So nice!
print("==一维==")
# 一维
a = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(a[:]) # [1 2 3 4 5 6 7 8 9]
print(a[1::2]) # [2 4 6 8]
# 负数表示从右到左,即-1表示从右到左且步长为1
print(a[::-1]) # [9 8 7 6 5 4 3 2 1]
print(a[2:4]) # [3 4]
print("==二维==")
# 二维
a = numpy.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(a.shape) # (3, 4)
print(a)
# [[1, 2, 3, 4],
# [5, 6, 7, 8],
# [9, 10, 11, 12]]
print(a[:2])
# [[1, 2, 3, 4],
# [5, 6, 7, 8]]
print(a[:2][:3])
# [[1, 2, 3, 4],
# [5, 6, 7, 8]]
print(a[1:][1:3, :3])
# [[9, 10, 11]]
print("----------")
print(a[:2, :2])
# [[1, 2],
# [5, 6]]
a[:2, :2] = [[66, 66], [55, 55]]
print(a) # a变了
# [[66, 66, 3, 4],
# [55, 55, 7, 8],
# [ 9, 10, 11, 12]]
print("==三维==")
# 三维
a = numpy.arange(60).reshape(3, 4, 5)
print(a.shape) # (3, 4, 5)
print(a)
# [[[ 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 32 33 34]
# [35 36 37 38 39]]
#
# [[40 41 42 43 44]
# [45 46 47 48 49]
# [50 51 52 53 54]
# [55 56 57 58 59]]]
print(a[:2])
# [[[ 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 32 33 34]
# [35 36 37 38 39]]]
print(a[1:][:2])
# [[[20 21 22 23 24]
# [25 26 27 28 29]
# [30 31 32 33 34]
# [35 36 37 38 39]]
#
# [[40 41 42 43 44]
# [45 46 47 48 49]
# [50 51 52 53 54]
# [55 56 57 58 59]]]
print(a[1:, :2])
# [[[20 21 22 23 24]
# [25 26 27 28 29]]
#
# [[40 41 42 43 44]
# [45 46 47 48 49]]]
print(a[1:][1:][:3])
# [[[40 41 42 43 44]
# [45 46 47 48 49]
# [50 51 52 53 54]
# [55 56 57 58 59]]]
print(a[1:, :2][:1])
# [[[20 21 22 23 24]
# [25 26 27 28 29]]]
print(a[:2, :3][1:, :2])
# [[[20 21 22 23 24]
# [25 26 27 28 29]]]
print(a[:2, 1:, :3])
# [[[ 5 6 7]
# [10 11 12]
# [15 16 17]]
#
# [[25 26 27]
# [30 31 32]
# [35 36 37]]]
print(a[:2, [0, 2], :2])
# [[[ 0 1]
# [10 11]]
#
# [[20 21]
# [30 31]]]
print(a[:2, [0, 2, 0, 2], :2])
# [[[ 0 1]
# [10 11]
# [ 0 1]
# [10 11]]
#
# [[20 21]
# [30 31]
# [20 21]
# [30 31]]]
print("----------")
b = a[1:, [1, 3]]
print(b)
# [[[25 26 27 28 29]
# [35 36 37 38 39]]
#
# [[45 46 47 48 49]
# [55 56 57 58 59]]]
print(b[:, :, [1, 3]])
# [[[26 28]
# [36 38]]
#
# [[46 48]
# [56 58]]]
print("----------")
# 省略号...的解释:
# 1.使得选择元组的长度与数组的维度相同。
# 2.同时表示在这些维度上全部截取。
print(a[..., 1:3])
# [[[ 1 2]
# [ 6 7]
# [11 12]
# [16 17]]
#
# [[21 22]
# [26 27]
# [31 32]
# [36 37]]
#
# [[41 42]
# [46 47]
# [51 52]
# [56 57]]]
print(a[:2, ..., 1:3])
# [[[ 1 2]
# [ 6 7]
# [11 12]
# [16 17]]
#
# [[21 22]
# [26 27]
# [31 32]
# [36 37]]]
print(a[..., [0, 2, 1, 0], 1:3])
# [[[ 1 2]
# [11 12]
# [ 6 7]
# [ 1 2]]
#
# [[21 22]
# [31 32]
# [26 27]
# [21 22]]
#
# [[41 42]
# [51 52]
# [46 47]
# [41 42]]]
print("==重点1:高级索引之布尔索引==")
# 我们可以通过一个布尔数组来索引目标数组。
condition = numpy.array([True, False, True])
print(a[condition])
# [[[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
#
# [[40 41 42 43 44]
# [45 46 47 48 49]
# [50 51 52 53 54]
# [55 56 57 58 59]]]
# 布尔索引通过布尔运算(如:比较运算符)来获取"符合条件的元素"的数组。
condition = a % 3 == 0
print(condition)
# [[[ True False False True False]
# [False True False False True]
# [False False True False False]
# [ True False False True False]]
#
# [[False True False False True]
# [False False True False False]
# [ True False False True False]
# [False True False False True]]
#
# [[False False True False False]
# [ True False False True False]
# [False True False False True]
# [False False True False False]]]
print(len(a[condition]), a[condition]) # 20
# [ 0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57]
# ~ 是取补运算符。
print(len(a[~condition]), a[~condition]) # 40
# [ 1 2 4 5 7 8 10 11 13 14 16 17 19 20 22 23 25 26 28 29 31 32 34 35
# 37 38 40 41 43 44 46 47 49 50 52 53 55 56 58 59]
print("==重点2:高级索引之整数数组索引==")
# 连续两个整数数组索引,且两整数数组的长度一致。
print(a[1:, [1, 3], [1, 3]]) # 后面是连续的两个整数数组
# [[26 38]
# [46 58]]
print(a[[0, 2], [0, 2]]) # 相当于[a[0][0], a[2][2]]
# [[ 0 1 2 3 4]
# [50 51 52 53 54]]
print("----------")
# 连续两个整数数组索引,且两整数数组的长度不一致(但是可以广播)。
print(a[[0, 1, 2], [2]]) # 相当于[a[0][2], a[1][2], a[2][2]]
# [[10 11 12 13 14]
# [30 31 32 33 34]
# [50 51 52 53 54]]
print("==重点3:高级索引之花式索引==")
# 2.传入多个索引数组(要使用np.ix_)
# 外围3*2的矩阵,相当于:
# [[a[0][0] a[0][2]]
# [a[1][0] a[1][2]]
# [a[2][0] a[2][2]]]
print(a[numpy.ix_([0, 1, 2], [0, 2])])
# [[[ 0 1 2 3 4]
# [10 11 12 13 14]]
#
# [[20 21 22 23 24]
# [30 31 32 33 34]]
#
# [[40 41 42 43 44]
# [50 51 52 53 54]]]
print("----------")
a = numpy.array([[1, 2, 3],
[2, 3, 4],
[4, 5, 6]])
print(a.shape)
print(a)
# 花式索引之传入单个索引数组
# 1.传入单个索引数组,表示取对应下标的元素。
print(a[:, [0, 2]])
# [[1, 3],
# [2, 4],
# [4, 6]]
print(a[:, [0, -1]])
# [[1, 3],
# [2, 4],
# [4, 6]]
print("----------")
# 花式索引之传入多个索引数组: numpy.ix_()
# 2.传入多个索引数组(要使用np.ix_)
# 外围3*2的矩阵,相当于:
# [[a[0][0] a[0][2]]
# [a[1][0] a[1][2]]
# [a[2][0] a[2][2]]]
print(a[numpy.ix_([0, 1, 2], [0, 2])])
# [[1, 3],
# [2, 4],
# [4, 6]]
运行结果:
==一维==
[1 2 3 4 5 6 7 8 9]
[2 4 6 8]
[9 8 7 6 5 4 3 2 1]
[3 4]
==二维==
(3, 4)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[1 2 3 4]
[5 6 7 8]]
[[1 2 3 4]
[5 6 7 8]]
[[ 9 10 11]]
----------
[[1 2]
[5 6]]
[[66 66 3 4]
[55 55 7 8]
[ 9 10 11 12]]
==三维==
(3, 4, 5)
[[[ 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 32 33 34]
[35 36 37 38 39]]
[[40 41 42 43 44]
[45 46 47 48 49]
[50 51 52 53 54]
[55 56 57 58 59]]]
[[[ 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 32 33 34]
[35 36 37 38 39]]]
[[[20 21 22 23 24]
[25 26 27 28 29]
[30 31 32 33 34]
[35 36 37 38 39]]
[[40 41 42 43 44]
[45 46 47 48 49]
[50 51 52 53 54]
[55 56 57 58 59]]]
[[[20 21 22 23 24]
[25 26 27 28 29]]
[[40 41 42 43 44]
[45 46 47 48 49]]]
[[[40 41 42 43 44]
[45 46 47 48 49]
[50 51 52 53 54]
[55 56 57 58 59]]]
[[[20 21 22 23 24]
[25 26 27 28 29]]]
[[[20 21 22 23 24]
[25 26 27 28 29]]]
[[[ 5 6 7]
[10 11 12]
[15 16 17]]
[[25 26 27]
[30 31 32]
[35 36 37]]]
[[[ 0 1]
[10 11]]
[[20 21]
[30 31]]]
[[[ 0 1]
[10 11]
[ 0 1]
[10 11]]
[[20 21]
[30 31]
[20 21]
[30 31]]]
----------
[[[25 26 27 28 29]
[35 36 37 38 39]]
[[45 46 47 48 49]
[55 56 57 58 59]]]
[[[26 28]
[36 38]]
[[46 48]
[56 58]]]
----------
[[[ 1 2]
[ 6 7]
[11 12]
[16 17]]
[[21 22]
[26 27]
[31 32]
[36 37]]
[[41 42]
[46 47]
[51 52]
[56 57]]]
[[[ 1 2]
[ 6 7]
[11 12]
[16 17]]
[[21 22]
[26 27]
[31 32]
[36 37]]]
[[[ 1 2]
[11 12]
[ 6 7]
[ 1 2]]
[[21 22]
[31 32]
[26 27]
[21 22]]
[[41 42]
[51 52]
[46 47]
[41 42]]]
==重点1:高级索引之布尔索引==
[[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
[[40 41 42 43 44]
[45 46 47 48 49]
[50 51 52 53 54]
[55 56 57 58 59]]]
[[[ True False False True False]
[False True False False True]
[False False True False False]
[ True False False True False]]
[[False True False False True]
[False False True False False]
[ True False False True False]
[False True False False True]]
[[False False True False False]
[ True False False True False]
[False True False False True]
[False False True False False]]]
20 [ 0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57]
40 [ 1 2 4 5 7 8 10 11 13 14 16 17 19 20 22 23 25 26 28 29 31 32 34 35
37 38 40 41 43 44 46 47 49 50 52 53 55 56 58 59]
==重点2:高级索引之整数数组索引==
[[26 38]
[46 58]]
[[ 0 1 2 3 4]
[50 51 52 53 54]]
----------
[[10 11 12 13 14]
[30 31 32 33 34]
[50 51 52 53 54]]
==重点3:高级索引之花式索引==
[[[ 0 1 2 3 4]
[10 11 12 13 14]]
[[20 21 22 23 24]
[30 31 32 33 34]]
[[40 41 42 43 44]
[50 51 52 53 54]]]
----------
(3, 3)
[[1 2 3]
[2 3 4]
[4 5 6]]
[[1 3]
[2 4]
[4 6]]
[[1 3]
[2 4]
[4 6]]
----------
[[1 3]
[2 4]
[4 6]]