NumPy 入门详细教程

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]]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容