第2章 Numpy库

目录

本文的Jupyter notebook脚本文件等请从百度网盘下载

第二章 Numpy库

2.0 引子

2.0.1 list VS. ndarray

numpy 的核心是 ndarray 对象(numpy 数组),它封装了 python 原生的同数据类型的 n 维数组(python 数组)。numpy 数组和 python 数组之间有几个重要的区别:

  • numpy 数组一旦创建,其元素数量就不能再改变了。 增删 ndarray 元素的操作,意味着创建一个新数组并删除原来的数组。python 数组的元素则可以动态增减不同,
  • numpy 数组中的元素都需要具有相同的数据类型,因此在内存中的大小相同。 python 数组则无此要求。
  • numpy 数组的方法涵盖了大量数学运算和复杂操作,许多方法在最外层的 numpy 命名空间中都有对应的映射函数。和 python 数组相比,numpy 数组的方法功能更强大,执行效率更高,代码更简洁。

然而,以上的差异并没有真正体现出 ndarray 的优势之所在,ndarray 的精髓在于 numpy 的两大特征:矢量化(vectorization)和广播(broadcast)。矢量化可以理解为代码中没有显式的循环、索引等,广播可以理解为隐式地对每个元素实施操作。矢量化和广播理解起来有点抽象,我们还是举个栗子来说明一下吧。

例题: a 和 b 是等长的两个整数数组,求 a 和 b 对应元素之积组成的数组。

1.用 python 数组实现:

c = list()
for i in range(len(a)): 
    c.append(a[i]*b[i])
    ```
用 numpy 数组实现:
```python
c = a*b
list1 = [1,2,3]
id(list1)
2323276417416
list1.append(4)
print(list1)
id(list1)
[1, 2, 3, 4]





2323276417416

2.0.2 dtype AND shape

子曰:找对象先了解品行,学对象先了解属性。
ndarray 对象有很多属性,详见下表。

属性说明
ndarray.dtype元素类型
ndarray.shape数组的结构
ndarray.ndim秩,即轴的数量或维度的数量
ndarray.size数组元素的个数
ndarray.itemsize每个元素的大小,以字节为单位
ndarray.flags数组的内存信息
ndarray.real元素的实部
ndarray.imag元素的虚部
ndarray.data数组元素的实际存储区

基于以下三个原因,我认为,dtype 和 shape 是 ndarray 最重要的两个属性,重要到几乎可以忽略其他的属性。

  • 我们趟过的坑,几乎都是 dtype 挖的
  • 我们的迷茫,几乎都是因为 shape 和我们期望的不一样
  • 我们的工作,很多都是在改变 shape

ndarray.astype() 可以修改元素类型 ,不能够直接对ndarray.dtype赋值进行更改
ndarray.reshape() 可以重新定义数组的结构,
这两个方法的重要性和其对应的属性一样。记住这两个属性和对应的两个方法,就算是登堂入室了。

import numpy as np
a = np.arange(5)
print(a)
a.dtype
[0 1 2 3 4]





dtype('int32')
a.dtype='float32'
print(a)
a.dtype
[0.e+00 1.e-45 3.e-45 4.e-45 6.e-45]





dtype('float32')

2.1 为什么要用Numpy

2.1.1  低效的Python for循环

【例】 求100万个数的倒数

import numpy as np
def compute_reciprocals(values):
    res = []
    for value in values:      # 每遍历到一个元素,就要判断其类型,并查找适用于该数据类型的正确函数
        res.append(1/value)
    return res


values = list(range(1, 1000000))
%timeit compute_reciprocals(values)
145 ms ± 13.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit :ipython中统计运行时间的魔术方法(多次运行取平均值)

values = np.arange(1, 1000000)
%timeit 1/values
2.64 ms ± 40.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

实现相同计算,Numpy的运行速度是Python循环的25倍,产生了质的飞跃

2.1.2  Numpy为什么如此高效

Numpy 是由C语言编写的

1、编译型语言VS解释型语言

C语言执行时,对代码进行整体编译,速度更快

2、连续单一类型存储VS分散多变类型存储

(1)Numpy数组内的数据类型必须是统一的,如全部是浮点型,而Python列表支持任意类型数据的填充

(2)Numpy数组内的数据连续存储在内存中,而Python列表的数据分散在内存中

这种存储结构,与一些更加高效的底层处理方式更加的契合

3、多线程VS线程锁

Python语言执行时有线程锁,无法实现真正的多线程并行,而C语言可以

2.1.3  什么时候用Numpy

在数据处理的过程中,遇到使用“Python for循环” 实现一些向量化、矩阵化操作的时候,要优先考虑用Numpy

如: 1、两个向量的点乘

   2、矩阵乘法

2.2 Numpy数组的创建

2.2.1 从列表开始创建

import numpy as np

x = np.array([1, 2, 3, 4, 5])
print(x)
[1 2 3 4 5]
print(type(x))
print(x.shape)
<class 'numpy.ndarray'>
(5,)
  • 设置数组的数据类型
x = np.array([1, 2, 3, 4, 5], dtype="float32")
print(x)
print(type(x))
print(type(x[0]))
[1. 2. 3. 4. 5.]
<class 'numpy.ndarray'>
<class 'numpy.float32'>
my_list = [1, 2, 3, 4, 5]
my_numpy_list = np.array(my_list) 
my_numpy_list
array([1, 2, 3, 4, 5])
q = my_numpy_list.astype(float)
q.dtype
dtype('float64')

  • 二维数组
x = np.array([[1, 2, 3],
             [4, 5, 6],
             [7, 8, 9]])
print(x)
print(x.shape)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
(3, 3)
my_list0 = [[1,2,3,9],[5,4,0,3],[7,4,8,1]]
mn = np.array(my_list0)   #创建二维数组
mn
array([[1, 2, 3, 9],
       [5, 4, 0, 3],
       [7, 4, 8, 1]])
?np.array
mn.tolist()  #数组转化为列表
[[1, 2, 3, 9], [5, 4, 0, 3], [7, 4, 8, 1]]

2.2.2 从头创建数组(利用方法生成特殊数组)

  • .zeros() : 全零
  • .ones() : 全1
  • .full() : 根据给定值填充
  • .eye() :单位阵(斜线上为1)
  • .arange() : 线性序列
  • .linspace() : 线性等分
  • .logspace() : 等比序列
  • 生成随机数数组
    • .random.random: 生成0~1之间数字构成的随机数数组
    • .random.normal: 生成正态分布的随机数数组
    • .random.randint:生成随机整数数组
    • .random.permutation: 基于已有的序列,随机重排序
    • .random.shuffle: 基于已有的序列,随机重排序
    • .random.choice: 从序列中随机选取出来组成数组
  • 依据已有数组的形状创建数组
    • .ones_like:
    • .zeros_like:
    • .full_like:

(1)np.zeros()

?np.zeros
# 创建长度为5的数组,值都为0
np.zeros(5, dtype=int)
array([0, 0, 0, 0, 0])
zero = np.zeros((2,3))   #产生形状为(2,3)全0的数组
zero
array([[0., 0., 0.],
       [0., 0., 0.]])

(2)np.ones

# 创建一个2*4的浮点型数组,值都为1
np.ones((2, 4), dtype=float)
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.]])
one = np.ones((6,3)) #产生形状为(6,3)全1的数组
one
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])

(3)np.full

np.full(5,9.9)
array([9.9, 9.9, 9.9, 9.9, 9.9])
# 创建一个3*5的数组,值都为8.8
np.full((3, 5), 8.8)
array([[8.8, 8.8, 8.8, 8.8, 8.8],
       [8.8, 8.8, 8.8, 8.8, 8.8],
       [8.8, 8.8, 8.8, 8.8, 8.8]])

(4)np.eye

?np.eye
# 创建一个3*3的单位矩阵
np.eye(3)
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
eye1 = np.eye(3,5)
eye1
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.]])

(5)np.arange

?np.arange
# 创建一个线性序列数组,从1开始,到15结束,步长为2
np.arange(1, 15, 2)
array([ 1,  3,  5,  7,  9, 11, 13])

(6)np.linspace

#创建一个4个元素的数组,这四个数均匀的分配到0~1
np.linspace(0, 1, 4)
array([0.        , 0.33333333, 0.66666667, 1.        ])

(7)np.logspace

# 创建一个10个元素的数组,形成1~10^9的等比数列
np.logspace(0, 9, 10)
array([1.e+00, 1.e+01, 1.e+02, 1.e+03, 1.e+04, 1.e+05, 1.e+06, 1.e+07,
       1.e+08, 1.e+09])

(8)np.random.random

# 创建一个3*3的,在0~1之间均匀分布的随机数构成的数组
np.random.random((3,3))
array([[0.24347952, 0.41715541, 0.41363866],
       [0.44869706, 0.18128167, 0.18568051],
       [0.05705023, 0.0689205 , 0.74837661]])

(9)np.random.normal

# 创建一个3*3的,均值为0,标准差为1的正态分布随机数构成的数组
np.random.normal(0, 1, (3,3))
array([[-0.38530465,  0.17474932,  0.31129291],
       [ 1.61626424, -2.18883854,  0.54043825],
       [-0.9141666 , -0.03804043, -0.6645122 ]])

(10)np.random.randint

# 创建一个3*3的,在[0,10)之间随机整数构成的数组
np.random.randint(0, 10, (3,3))
array([[9, 1, 9],
       [0, 3, 9],
       [8, 5, 4]])

(11)np.random.permutation

# 随机重排列
x = np.array([10, 20, 30, 40])
np.random.permutation(x)       # 生产新列表
array([20, 40, 10, 30])
print(x)
np.random.shuffle(x)          # 修改原列表
print(x)
[10 20 30 40]
[20 40 10 30]

(12)np.random.choice

  • 按指定形状采样 随机采样
x = np.arange(10, 25, dtype = float)
x
array([10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22.,
       23., 24.])
np.random.choice(x, size=(4, 3))
array([[19., 23., 22.],
       [22., 21., 13.],
       [15., 21., 17.],
       [14., 23., 19.]])
import numpy as np
np.random.choice(10, 10)
array([0, 4, 3, 7, 0, 5, 2, 5, 1, 9])
x = np.arange(5).reshape(1, 5)
x
x.sum(axis=1, keepdims=True)
array([[10]])
  • 按概率采样
np.random.choice(x, size=(4, 3), p=x/np.sum(x))
array([[15., 21., 20.],
       [23., 17., 18.],
       [23., 15., 17.],
       [19., 24., 22.]])

2.2.3 Numpy中的常数

  • 正无穷:Inf=inf=infty=Infinity=PINF
  • 负无穷:NINF
  • 正零: PZERO
  • 负零: NZERO
  • 非数值:nan=NaN=NAN
  • 自然数:e
  • π \pi π: pi
  • 伽马:euler_gamma
  • None: newaxis
print(np.inf)
print(np.NINF)
print(np.PZERO)
print(np.NZERO)
print(np.nan)
print(np.e)
print(np.pi)
print(np.euler_gamma)
print(np.newaxis)
inf
-inf
0.0
-0.0
nan
2.718281828459045
3.141592653589793
0.5772156649015329
None

2.3 Numpy多维数组轴的理解与操作控制

2.3.1 一维数组的轴(特例)

一维NumPy数组只有一个轴(即axis=0)

在这里插入图片描述

2.3.2 二维数组轴的理解

在二维NumPy数组中,轴是沿行和列的方向
在这里插入图片描述

  • AXIS 0 轴是沿着行(rows)的方向

在NumPy数组中,axis 0 是第一轴。对于二维或多维数组,axis 0 是沿行(row)向下的轴。(一维数组是特例,不适用此处解释,后续讲解)
在这里插入图片描述

  • AXIS 1 轴是沿着列(columns)的方向

在NumPy数组中,axis 1 是第2根轴。对于二维或多维数组,axis 1 是沿列(columns)横穿的轴。
在这里插入图片描述

2.3.3 三维与多维数组

在这里插入图片描述

  • 结合图像的理解:

    • 二维图像,灰度图
      在这里插入图片描述
  • 结合图像的理解:

    • 三位图像,RGB彩色图
      在这里插入图片描述

2.3.4 axis控制运算的轴方向

在带有axis参数的二维数组上使用np.sum()等聚合函数时,它会将二维数组折叠为一维数组。它会折叠数据并减少维度。

axis参数控制将聚合哪个轴,换句话说,axis参数控制哪个轴将被折叠。

将NumPy和函数与axis参数一起使用时,指定的轴是折叠的轴。

示例,先创建一个简单的数组:
在这里插入图片描述
分别使用 axis= 0 和 axis= 1 的NumPy求和函数sum:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

另一个高维Numpy进行堆叠的例子

import numpy  as np
a = np.array([[1, 2, 3, 44], [22, 32, 42, 42], [23, 3, 3, 43]])
b = np.array([[2, 3, 4, 44], [42, 52, 62, 42], [23, 3, 3, 43]])
print(a)
print(b)
print("\n")

# 合并a b两个数组
print("===========np.stack((a, b), axis=0)==========")
print(np.stack((a, b), axis=0))  # 2,3,4

print("===========np.stack((a, b), axis=1)==========")
print(np.stack((a, b), axis=1)) 

print("===========np.stack((a, b), axis=2)==========")
print(np.stack((a, b), axis=2))  
[[ 1  2  3 44]
 [22 32 42 42]
 [23  3  3 43]]
[[ 2  3  4 44]
 [42 52 62 42]
 [23  3  3 43]]


===========np.stack((a, b), axis=0)==========
[[[ 1  2  3 44]
  [22 32 42 42]
  [23  3  3 43]]

 [[ 2  3  4 44]
  [42 52 62 42]
  [23  3  3 43]]]
===========np.stack((a, b), axis=1)==========
[[[ 1  2  3 44]
  [ 2  3  4 44]]

 [[22 32 42 42]
  [42 52 62 42]]

 [[23  3  3 43]
  [23  3  3 43]]]
===========np.stack((a, b), axis=2)==========
[[[ 1  2]
  [ 2  3]
  [ 3  4]
  [44 44]]

 [[22 42]
  [32 52]
  [42 62]
  [42 42]]

 [[23 23]
  [ 3  3]
  [ 3  3]
  [43 43]]]

2.4 Numpy数组的性质

2.4.1 数组的属性

  • shape: 形状
  • ndim:维度
  • size:数组中元素的个数
  • itemsize:数组中每个元素的空间大小,以字节为单位
  • dtype:返回数组元素的数据类型
  • nbytes:所有元素所占空间的大小,以字节为单位
x = np.random.randint(10, size=(3, 4))
x
array([[8, 6, 6, 1],
       [3, 1, 1, 8],
       [2, 9, 8, 3]])

1、数组的形状shape

x.shape
(3, 4)

2、数组的维度ndim

x.ndim
2
y = np.arange(10)
y
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
y.ndim
1

3、数组的大小size

x.size
12

4、每个元素所占空间的大小itemsize

x.itemsize
4

5、数组的数据类型dtype

x.dtype
dtype('int32')

6、数组所有元素所占空间的大小nbytes

x.nbytes
48

2.4.2 数组索引

1、一维数组的索引

x1 = np.arange(10)
x1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
x1[0]
0
x1[5]
5
x1[-1]
9

2、多维数组的索引——以二维为例

x2 = np.random.randint(0, 20, (2,3))
x2
array([[ 7,  8, 18],
       [ 5, 13, 13]])
x2[0, 2]
18
x2[0][2]
18

注意:numpy数组的数据类型是固定的,向一个整型数组插入一个浮点值,浮点值会向下进行取整

x2[0, 0] = 1.618
x2
array([[ 1,  8, 18],
       [ 5, 13, 13]])

2.4.3 数组的切片

1、一维数组——跟列表一样

x1 = np.arange(10)
x1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
x1[:3]
array([0, 1, 2])
x1[3:]
array([3, 4, 5, 6, 7, 8, 9])
x1[::-1]
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

2、多维数组——以二维为例

x2 = np.random.randint(20, size=(3,4)) 
x2
array([[12, 12,  8, 18],
       [12,  1, 16,  4],
       [14, 13,  5,  1]])
x2[1,1]
1
x2[:2, :3]             # 前两行,前三列
array([[12, 12,  8],
       [12,  1, 16]])
x2[1]  # 把二维看作一个列表,第2个元素
array([12,  1, 16,  4])
x2[:2, 0:3:2]       # 前两行 前三列(每隔一列)
array([[14, 15],
       [18, 16]])
x2[::-1, ::-1]
array([[17,  2,  8,  0],
       [17, 16,  8, 18],
       [ 8, 15,  9, 14]])
x3 = np.random.randint(60, size=(3,4,5)) 
x3
array([[[33, 13, 57, 41, 29],
        [ 0, 14, 26, 36, 26],
        [48,  5, 30, 59, 55],
        [28, 23, 14, 16, 43]],

       [[17, 55, 21, 37,  9],
        [22,  7, 25, 39, 33],
        [57, 48,  0, 46, 37],
        [17, 47,  2, 33, 42]],

       [[13, 31, 45,  2, 18],
        [16, 10, 28, 27,  1],
        [32, 46, 54, 44, 10],
        [ 9, 20, 20,  2, 54]]])
x3[0]
array([[33, 13, 57, 41, 29],
       [ 0, 14, 26, 36, 26],
       [48,  5, 30, 59, 55],
       [28, 23, 14, 16, 43]])
x3[0,0]
array([33, 13, 57, 41, 29])
x3[0,0,0]
33

3、获取数组的行和列

x3 = np.random.randint(20, size=(3,4)) 
x3
array([[ 8, 13, 15,  7],
       [19, 13, 17,  6],
       [11,  2,  0, 12]])
x3[1, :]   #第一行  从0开始计数
array([19, 13, 17,  6])
x3[1]    # 第一行简写
array([19, 13, 17,  6])
x3[:, 2]  # 第二列   从0开始计数
array([15, 17,  0])

4、切片获取的是视图,而非副本

x4 = np.random.randint(20, size=(3,4)) 
x4
array([[ 5, 14,  7,  2],
       [ 8, 12,  9,  3],
       [19,  0, 10,  7]])
x5 = x4[:2, :2]
x5
array([[ 5, 14],
       [ 8, 12]])

注意:视图元素发生修改,则原数组亦发生相应修改

x5[0, 0] = 0
x5
array([[ 0, 14],
       [ 8, 12]])
x4
array([[ 0, 14,  7,  2],
       [ 8, 12,  9,  3],
       [19,  0, 10,  7]])

修改切片的安全方式:copy

x4 = np.random.randint(20, size=(3,4)) 
x4
array([[18, 14, 10, 12],
       [10, 16,  7, 19],
       [ 3, 16,  3, 12]])
x6 = x4[:2, :2].copy()
x6
array([[18, 14],
       [10, 16]])
x6[0, 0] = 0
x6
array([[ 0, 14],
       [10, 16]])
x4
array([[18, 14, 10, 12],
       [10, 16,  7, 19],
       [ 3, 16,  3, 12]])

2.4.4 数组的变形

x5 = np.random.randint(0, 10, (12,))
x5
array([7, 5, 1, 5, 2, 3, 0, 1, 8, 5, 9, 1])
x5.shape
(12,)
x6 = x5.reshape(3, 4)
x6
array([[7, 5, 1, 5],
       [2, 3, 0, 1],
       [8, 5, 9, 1]])

注意:reshape返回的是视图,而非副本

x6[0, 0] = 0
x5
array([0, 5, 1, 5, 2, 3, 0, 1, 8, 5, 9, 1])

一维向量转行向量

x5.ndim
1
x7 = x5.reshape(1, x5.shape[0])    
x7
array([[0, 5, 1, 5, 2, 3, 0, 1, 8, 5, 9, 1]])
x7.ndim
2
x8 = x5[np.newaxis, :]
x8
array([[0, 5, 1, 5, 2, 3, 0, 1, 8, 5, 9, 1]])

一维向量转列向量

x7 = x5.reshape(x5.shape[0], 1)    
x7
array([[0],
       [5],
       [1],
       [5],
       [2],
       [3],
       [0],
       [1],
       [8],
       [5],
       [9],
       [1]])
x8 = x5[:, np.newaxis]
x8
array([[0],
       [5],
       [1],
       [5],
       [2],
       [3],
       [0],
       [1],
       [8],
       [5],
       [9],
       [1]])

多维向量转一维向量

x6 = np.random.randint(0, 10, (3, 4))
x6
array([[3, 7, 6, 4],
       [4, 5, 6, 3],
       [7, 6, 2, 3]])

flatten返回的是副本

x9 = x6.flatten()
x9
array([3, 7, 6, 4, 4, 5, 6, 3, 7, 6, 2, 3])
x9[0]=0
x6
array([[3, 7, 6, 4],
       [4, 5, 6, 3],
       [7, 6, 2, 3]])

ravel返回的是视图

x10 = x6.ravel()
x10
array([3, 7, 6, 4, 4, 5, 6, 3, 7, 6, 2, 3])
x10[0]=0
x6
array([[0, 7, 6, 4],
       [4, 5, 6, 3],
       [7, 6, 2, 3]])

reshape返回的是视图

x11 = x6.reshape(-1)
x11
array([0, 7, 6, 4, 4, 5, 6, 3, 7, 6, 2, 3])
x11[0]=10
x6
array([[10,  7,  6,  4],
       [ 4,  5,  6,  3],
       [ 7,  6,  2,  3]])

2.4.5 数组的拼接

x1 = np.array([[1, 2, 3],
              [4, 5, 6]])
x2 = np.array([[7, 8, 9],
              [0, 1, 2]])

1、水平拼接——非视图

x3 = np.hstack([x1, x2])
x3
array([[1, 2, 3, 7, 8, 9],
       [4, 5, 6, 0, 1, 2]])
x3[0][0] = 0
x1
array([[1, 2, 3],
       [4, 5, 6]])
x4 = np.c_[x1, x2]
x4
array([[1, 2, 3, 7, 8, 9],
       [4, 5, 6, 0, 1, 2]])
x4[0][0] = 0
x1
array([[1, 2, 3],
       [4, 5, 6]])

2、垂直拼接——非视图

x1 = np.array([[1, 2, 3],
              [4, 5, 6]])
x2 = np.array([[7, 8, 9],
              [0, 1, 2]])
x5 = np.vstack([x1, x2])
x5
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9],
       [0, 1, 2]])
x6 = np.r_[x1, x2]
x6
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9],
       [0, 1, 2]])

2.4.6 数组的分裂

1、split的用法

x6 = np.arange(10)
x6
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
x1, x2, x3 = np.split(x6, [2, 7])
print(x1, x2, x3)
[0 1] [2 3 4 5 6] [7 8 9]

2、hsplit的用法

x7 = np.arange(1, 26).reshape(5, 5)
x7
array([[ 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]])
left, middle, right = np.hsplit(x7, [2,4])
print("left:\n", left)            # 第0~1列
print("middle:\n", middle)        # 第2~3列
print("right:\n", right)          # 第4列
left:
 [[ 1  2]
 [ 6  7]
 [11 12]
 [16 17]
 [21 22]]
middle:
 [[ 3  4]
 [ 8  9]
 [13 14]
 [18 19]
 [23 24]]
right:
 [[ 5]
 [10]
 [15]
 [20]
 [25]]

3、vsplit的用法

x7 = np.arange(1, 26).reshape(5, 5)
x7
array([[ 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]])
upper, middle, lower = np.vsplit(x7, [2,4])
print("upper:\n", upper)         # 第0~1行
print("middle:\n", middle)       # 第2~3行
print("lower:\n", lower)         # 第4行
upper:
 [[ 1  2  3  4  5]
 [ 6  7  8  9 10]]
middle:
 [[11 12 13 14 15]
 [16 17 18 19 20]]
lower:
 [[21 22 23 24 25]]

2.5 Numpy四大运算

2.5.1 向量化运算

1、与数字的加减乘除等

x1 = np.arange(1,6)
x1
array([1, 2, 3, 4, 5])
print("x1+5", x1+5)
print("x1-5", x1-5)
print("x1*5", x1*5)
print("x1/5", x1/5)
x1+5 [ 6  7  8  9 10]
x1-5 [-4 -3 -2 -1  0]
x1*5 [ 5 10 15 20 25]
x1/5 [0.2 0.4 0.6 0.8 1. ]
print("-x1", -x1)
print("x1**2", x1**2)
print("x1//2", x1//2)
print("x1%2", x1%2)
-x1 [-1 -2 -3 -4 -5]
x1**2 [ 1  4  9 16 25]
x1//2 [0 1 1 2 2]
x1%2 [1 0 1 0 1]
# 注意区别于list的加减
list1 = [1,2,3,4,5]
list1+[6]
[1, 2, 3, 4, 5, 6]

2、绝对值、三角函数、指数、对数

(1)绝对值

x2 = np.array([1, -1, 2, -2, 0])
x2
array([ 1, -1,  2, -2,  0])
abs(x2)
array([1, 1, 2, 2, 0])
np.abs(x2)
array([1, 1, 2, 2, 0])

(2)三角函数

theta = np.linspace(0, np.pi, 3)
theta
array([0.        , 1.57079633, 3.14159265])
print("sin(theta)", np.sin(theta))
print("con(theta)", np.cos(theta))
print("tan(theta)", np.tan(theta))
sin(theta) [0.0000000e+00 1.0000000e+00 1.2246468e-16]
con(theta) [ 1.000000e+00  6.123234e-17 -1.000000e+00]
tan(theta) [ 0.00000000e+00  1.63312394e+16 -1.22464680e-16]
x = [1, 0 ,-1]
print("arcsin(x)", np.arcsin(x))
print("arccon(x)", np.arccos(x))
print("arctan(x)", np.arctan(x))
arcsin(x) [ 1.57079633  0.         -1.57079633]
arccon(x) [0.         1.57079633 3.14159265]
arctan(x) [ 0.78539816  0.         -0.78539816]

(3)指数运算

x = np.arange(3)
x
array([0, 1, 2])
np.exp(x)
array([1.        , 2.71828183, 7.3890561 ])

(4)对数运算

x = np.array([1, 2, 4, 8 ,10])
print("ln(x)", np.log(x))
print("log2(x)", np.log2(x))
print("log10(x)", np.log10(x))
ln(x) [0.         0.69314718 1.38629436 2.07944154 2.30258509]
log2(x) [0.         1.         2.         3.         3.32192809]
log10(x) [0.         0.30103    0.60205999 0.90308999 1.        ]

3、两个数组的运算

x1 = np.arange(1,6)
x1
array([1, 2, 3, 4, 5])
x2 = np.arange(6,11)
x2
array([ 6,  7,  8,  9, 10])
print("x1+x2:", x1+x2)
print("x1-x2:", x1-x2)
print("x1*x2:", x1*x2)
print("x1/x2:", x1/x2)
x1+x2: [ 7  9 11 13 15]
x1-x2: [-5 -5 -5 -5 -5]
x1*x2: [ 6 14 24 36 50]
x1/x2: [0.16666667 0.28571429 0.375      0.44444444 0.5       ]

注意区别于list运算

list1 = list(range(1,6))
print(list1)
list2 = list(range(6,11))
print(list2)
list1+list2
[1, 2, 3, 4, 5]
[6, 7, 8, 9, 10]





[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

2.5.2 矩阵运算

x = np.arange(9).reshape(3, 3)
x
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
  • 矩阵的转置
y = x.T
y
array([[0, 3, 6],
       [1, 4, 7],
       [2, 5, 8]])
  • 矩阵乘法
x = np.array([[1, 0],
             [1, 1]])
y = np.array([[0, 1],
             [1, 1]])
x.dot(y)
array([[0, 1],
       [1, 2]])
np.dot(x, y)
array([[0, 1],
       [1, 2]])
y.dot(x)
array([[1, 1],
       [2, 1]])
np.dot(y, x)
array([[1, 1],
       [2, 1]])

注意跟x*y的区别

  • 元素对应相乘
x*y
array([[0, 0],
       [1, 1]])

2.5.3 广播运算

举个栗子
a = 2
print("a\n", a,"\n") 
b = np.array([1,2])
print("b\n",b,"\n") 
c = np.arange(1,7).reshape(3,2)
print("c\n",c,"\n") 
d = np.arange(1,9).reshape(2,2,2)
print("d\n",d,"\n")
e = np.arange(1,5).reshape(2,2)
print("e\n",e,"\n")
a
 2 

b
 [1 2] 

c
 [[1 2]
 [3 4]
 [5 6]] 

d
 [[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]] 

e
 [[1 2]
 [3 4]] 
  • ① 标量和一维、二维、三维数组之间的广播运算
print("a\n",a,"\n")
print("b\n",b,"\n")
print("a+b\n",a+b,"\n")
a
 2 

b
 [1 2] 

a+b
 [3 4] 
print("a\n",a,"\n")
print("c\n",c,"\n")
print("a+c\n",a+c,"\n")
a
 2 

c
 [[1 2]
 [3 4]
 [5 6]] 

a+c
 [[3 4]
 [5 6]
 [7 8]] 
print("a\n",a,"\n")
print("d\n",d,"\n")
print("a+d\n",a+d,"\n")
a
 2 

d
 [[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]] 

a+d
 [[[ 3  4]
  [ 5  6]]

 [[ 7  8]
  [ 9 10]]] 
  • ② 一维数组和二维、三维数组之间的广播运算
print("b\n",b,"\n")
print("c\n",c,"\n")
print("b+c\n",b+c,"\n")
b
 [1 2] 

c
 [[1 2]
 [3 4]
 [5 6]] 

b+c
 [[2 4]
 [4 6]
 [6 8]] 
print("b\n",b,"\n")
print("d\n",d,"\n")
print("b+d\n",b+d,"\n")
b
 [1 2] 

d
 [[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]] 

b+d
 [[[ 2  4]
  [ 4  6]]

 [[ 6  8]
  [ 8 10]]] 
  • ③ 二维数组和三维数组元素之间的广播运算
print("e\n",e,"\n")
print("d\n",d,"\n")
print("e+d\n",e+d,"\n")
e
 [[1 2]
 [3 4]] 

d
 [[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]] 

e+d
 [[[ 2  4]
  [ 6  8]]

 [[ 6  8]
  [10 12]]] 
print("c\n",c,"\n")
print("d\n",d,"\n")
print("c+d\n",c+d,"\n")
c
 [[1 2]
 [3 4]
 [5 6]] 

d
 [[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]] 




---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-27-e2835d3806eb> in <module>
      1 print("c\n",c,"\n")
      2 print("d\n",d,"\n")
----> 3 print("c+d\n",c+d,"\n")


ValueError: operands could not be broadcast together with shapes (3,2) (2,2,2) 

可以看出:不同形状数组之间,有时候可以触发广播机制,有时候却又不能。那么,触发广播机制,需要什么条件呢?

触发“广播机制”的条件

观察下面的表:
在这里插入图片描述

记住下面两句话:

  • 对于一个标量,可以将这一个数字的形状看成是一行一列;
  • 对于一个一维数组,可以将它的形状看成是一行多列;

对上述表和上面两句话,了解后,仔细观察下图:
在这里插入图片描述

不同形状的数组之间能不能触发广播机制,主要看对应形状的每一个位置上的数字,是否满足如下要求:

  • ① 要么对应位置上的数字完全一致,可以触发广播机制,比如说第Ⅵ组;
  • ② 对应位置上的数字要是不一样,那么对应位置上,必须有一个数字是1,比如说Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ;
  • ③ 如果对应位置上的数字不仅不相同,且没有任何一个的数字为1,那么就不能使用广播机制,比如说Ⅶ。

2.5.4 比较运算和掩码

  • all:所有元素满足条件
  • any:至少有一个满足条件
  • unique:元素唯一化

1、比较运算

x1 = np.random.randint(100, size=(10,10))
x1
array([[57, 50, 47, 45, 38, 31, 39, 82, 72, 57],
       [71, 38,  2, 69, 54, 61, 74, 77, 65, 39],
       [78, 74,  0, 44, 79, 32, 84, 79, 53,  8],
       [31, 94, 14, 43, 11, 32, 55, 35, 12,  3],
       [95, 89,  9, 14, 99, 64, 30, 17, 74,  9],
       [ 2, 42, 62, 36, 76, 39,  8, 46, 39, 87],
       [26, 77, 79, 45,  6, 90, 33,  7, 15, 34],
       [54, 80, 60, 24, 58, 29, 53, 14, 64, 58],
       [48, 22,  3, 71, 24, 23, 74, 13, 73, 22],
       [79,  7, 65, 66, 60, 34,  3, 66, 10, 55]])
x1 > 50
array([[ True, False, False, False, False, False, False,  True,  True,
         True],
       [ True, False, False,  True,  True,  True,  True,  True,  True,
        False],
       [ True,  True, False, False,  True, False,  True,  True,  True,
        False],
       [False,  True, False, False, False, False,  True, False, False,
        False],
       [ True,  True, False, False,  True,  True, False, False,  True,
        False],
       [False, False,  True, False,  True, False, False, False, False,
         True],
       [False,  True,  True, False, False,  True, False, False, False,
        False],
       [ True,  True,  True, False,  True, False,  True, False,  True,
         True],
       [False, False, False,  True, False, False,  True, False,  True,
        False],
       [ True, False,  True,  True,  True, False, False,  True, False,
         True]])

2、操作布尔数组

import numpy as np
x2 = np.random.randint(10, size=(3, 4))
x2
array([[6, 8, 1, 9],
       [7, 7, 1, 0],
       [9, 4, 6, 6]])
print(x2 > 5)
np.sum(x2 > 5)
[[ True  True False  True]
 [ True  True False False]
 [ True False  True  True]]





8
np.all(x2 > 5)
False
x2>1
array([[ True,  True, False,  True],
       [ True,  True, False, False],
       [ True,  True,  True,  True]])
np.all(x2>1, axis=1)
array([False, False,  True])
np.any(x2 == 9)
True
x2
array([[4, 3, 8, 8],
       [8, 9, 5, 1],
       [8, 5, 2, 4]])
(x2 < 9) & (x2 >5)
array([[False, False,  True,  True],
       [ True, False, False, False],
       [ True, False, False, False]])
np.sum((x2 < 9) & (x2 >5))
4
np.sum(x2[(x2<9)&(x2>5)])
32

3、将布尔数组作为掩码

x2
array([[1, 4, 2, 9],
       [8, 8, 2, 4],
       [9, 5, 3, 6]])
x2 > 5
array([[False, False, False,  True],
       [ True,  True, False, False],
       [ True, False, False,  True]])
x2[x2 > 5]
array([9, 8, 8, 9, 6])

4、元素唯一化

import numpy as np
arr = np.array([12, 11, 34, 23, 12, 8, 11])
# 查找数组的唯一元素
print(np.unique(arr))
[ 8 11 12 23 34]

2.5.5 花式索引与布尔索引

2.5.5.1 花式索引

1、一维数组

x = np.random.randint(100, size=10)
x
array([43, 69, 67,  9, 11, 27, 55, 93, 23, 82])

注意:结果的形状与索引数组ind一致

ind = [2, 6, 9]
x[ind]
array([67, 55, 82])
ind = np.array([[1, 0],
               [2, 3]])
x[ind]
array([[69, 43],
       [67,  9]])

2、多维数组

x = np.arange(12).reshape(3, 4)
x
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
row = np.array([0, 1, 2])
col = np.array([1, 3, 0])
x[row, col]               # x(0, 1) x(1, 3) x(2, 0)
array([1, 7, 8])
row[:, np.newaxis]       # 列向量
array([[0],
       [1],
       [2]])
x[row[:, np.newaxis], col]    # 广播机制
array([[ 1,  3,  0],
       [ 5,  7,  4],
       [ 9, 11,  8]])
2.5.5.2 布尔索引
array_2d = np.arange(1, 10).reshape((3, 3))    
print(array_2d)
print("------------")
# 使用布尔索引访问数组
print(array_2d > 5)
print("------------")
print(array_2d[array_2d > 5])
[[1 2 3]
 [4 5 6]
 [7 8 9]]
------------
[[False False False]
 [False False  True]
 [ True  True  True]]
------------
[6 7 8 9]
array_2d = np.arange(1, 10).reshape((3, 3))    
print(array_2d)
print("------------")
# 使用布尔索引访问数组
print(array_2d % 2 == 1)
print("------------")
print(array_2d[array_2d % 2 == 1])
[[1 2 3]
 [4 5 6]
 [7 8 9]]
------------
[[ True False  True]
 [False  True False]
 [ True False  True]]
------------
[1 3 5 7 9]

2.6 其他Numpy通用函数

2.6.1 数值排序

x = np.random.randint(20, 50, size=10)
x
array([48, 27, 44, 24, 34, 21, 24, 30, 34, 46])
  • 产生新的排序数组
np.sort(x)
array([21, 24, 24, 27, 30, 34, 34, 44, 46, 48])
x
array([48, 27, 44, 24, 34, 21, 24, 30, 34, 46])
  • 替换原数组
x.sort()
x
array([21, 24, 24, 27, 30, 34, 34, 44, 46, 48])
  • 获得排序索引
x = np.random.randint(20, 50, size=10)
x
array([27, 36, 35, 28, 34, 20, 21, 49, 48, 30])
i = np.argsort(x)
i
array([5, 6, 0, 3, 9, 4, 2, 1, 8, 7], dtype=int64)

2.6.2 最大最小值

x = np.random.randint(20, 50, size=10)
x
array([48, 31, 30, 44, 48, 33, 44, 48, 39, 35])
print("max:", np.max(x))
print("min:", np.min(x))
max: 48
min: 30
print("max_index:", np.argmax(x))
print("min_index:", np.argmin(x))
max_index: 0
min_index: 2

2.6.3 数值求和、求积

x = np.arange(1,6)
x
array([1, 2, 3, 4, 5])
x.sum()
15
np.sum(x)
15
x1 = np.arange(6).reshape(2,3)
x1
array([[0, 1, 2],
       [3, 4, 5]])
  • 按行求和
np.sum(x1, axis=1)
array([ 3, 12])
  • 按列求和
np.sum(x1, axis=0)
array([3, 5, 7])
  • 全体求和
np.sum(x1)
15
  • 求积
x
array([1, 2, 3, 4, 5])
x.prod()
120
np.prod(x)
120

2.6.4 中位数、均值、方差、标准差

x = np.random.normal(0, 1, size=10000)
import matplotlib.pyplot as plt

plt.hist(x, bins=50)
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xXctxT82-1647677176517)(output_327_0.png)]

  • 中位数
np.median(x)
-0.01024418366119727
  • 均值
x.mean()
-0.004164442327293362
np.mean(x)
-0.004164442327293362
  • 方差
x.var()
1.0221853234535774
np.var(x)
1.0221853234535774
  • 标准差
x.std()
1.0110318112965473
np.std(x)
1.0110318112965473
import numpy as np
x1 = np.array([[1,2,3,4],
                [2,3,4,5]])
x2 = [3,4,5,6]
print(x1+x2)

[[ 4  6  8 10]
 [ 5  7  9 11]]
{2,3,5,8}-{1,2,3,4,6}
{5, 8}

2.6.5 数组转置函数

  • T属性:
  • swapaxes():
  • transpose():

1、T属性

import numpy as np
arr = np.arange(10).reshape(2,5)
print(f"arr形状:{arr.shape}")
print(arr)
arr形状:(2, 5)
[[0 1 2 3 4]
 [5 6 7 8 9]]
# 使用T属性进行转置
new_arr = arr.T
print(f"new_arr形状:{new_arr.shape}")
print(new_arr)
new_arr形状:(5, 2)
[[0 5]
 [1 6]
 [2 7]
 [3 8]
 [4 9]]

2、swapaxes()

import numpy as np
arr = np.arange(24).reshape(2, 3, 4)
print(f"arr形状:{arr.shape}")
print(arr)
arr形状:(2, 3, 4)
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
# 使用swapaxes()方法进行数组转置,互换1号轴和2号轴的元素
new_arr = arr.swapaxes(2, 1)
print(f"new_arr形状:{new_arr.shape}")
print(new_arr)
new_arr形状:(2, 4, 3)
[[[ 0  4  8]
  [ 1  5  9]
  [ 2  6 10]
  [ 3  7 11]]

 [[12 16 20]
  [13 17 21]
  [14 18 22]
  [15 19 23]]]

3、transpose()

import numpy as np
arr = np.arange(24).reshape(2,3,4)
print(f"arr形状:{arr.shape}")
print(arr)
arr形状:(2, 3, 4)
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
# 使用transpose()方法进行转置
new_arr = arr.transpose((1,2,0))
print(f"new_arr形状:{new_arr.shape}")
print(new_arr)
new_arr形状:(3, 4, 2)
[[[ 0 12]
  [ 1 13]
  [ 2 14]
  [ 3 15]]

 [[ 4 16]
  [ 5 17]
  [ 6 18]
  [ 7 19]]

 [[ 8 20]
  [ 9 21]
  [10 22]
  [11 23]]]
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: NumPy是一个用于进行科学计算的Python库,提供了丰富的多维数组操作函数和工具。它是构建在Python的原始数据类型之上的,能够高效地进行大规模数据处理和数值计算。 NumPy的中文手册(CHM)是通过该库的官方文档翻译而来的。该手册详细介绍了NumPy的各种功能和用法,方便初学者快速上手,并提供了深入的技术指南和实用示例供进阶使用。 该手册内容涵盖了NumPy数组的创建和操作、数组索引和切片、数组的数学运算和统计方法、数组的形状和维度变换、数组的文件输入输出等。此外,手册还介绍了NumPy的广播机制、通用函数、线性代数、随机数生成等高级功能和应用。 通过使用该手册,用户能够快速掌握NumPy的基本概念和操作,能够灵活地处理各种数据类型,进行数据的查询、运算、转置、排序等各种操作。此外,手册还提供了对于NumPy的扩展库和第三方工具的介绍和链接,使用户能够进一步了解和应用NumPy在科学计算和数据处理领域的广泛应用。 总之,NumPy的中文手册(CHM)是一个非常实用的工具,能够帮助用户深入理解和掌握NumPy库的核心功能和应用,为科学计算和数据处理提供强大的支持。 ### 回答2: NumPy是一个开源的Python科学计算库,用于处理大型多维数组和矩阵。它不仅提供了一个高效的数据结构,还包含了许多用于数组操作的函数。 NumPy的中文手册chm包含了对NumPy库的详细介绍和使用指南。这个手册可以帮助用户了解NumPy的核心概念,并提供了丰富的示例代码来演示如何使用NumPy进行数据处理。 手册中包含了NumPy数组的创建、操作、索引等基本操作的说明。它还介绍了NumPy提供的各种数学函数和统计函数,如加法、减法、乘法、除法、平方、平方根等。用户可以通过这些函数对数组进行各种运算和统计分析。 此外,手册还介绍了NumPy数组的高级操作,如数组转置、重塑、连接、切片等。这些方法可以使用户更方便地进行数组的操作和处理。 手册还包含了NumPy的广播机制、向量化操作和ufunc函数等高级特性的说明。这些特性可以帮助用户高效地处理大规模的数组数据,提高计算速度和代码的简洁性。 总之,NumPy数据处理中文手册chm提供了全面而详细的NumPy库的说明和使用指南。通过阅读和学习这个手册,用户可以掌握NumPy的使用方法,更好地进行数据处理和科学计算。它是NumPy库的重要参考资料,对于使用NumPy进行数据处理的用户非常有价值。 ### 回答3: NumPy是一个用于数值计算的Python库,它提供了丰富的数学函数和高效的多维数组对象。NumPy的数据处理中文手册(chm)是一个详细的中文文档,涵盖了NumPy库的各种特性和用法,旨在帮助用户学习和使用NumPy进行数据处理。 这份中文手册包含了NumPy的安装方法、常用数据类型和数组操作函数的详细介绍,以及使用NumPy进行数据处理的各种技巧和例子。手册按照节组织,每个节都涵盖了特定主题。例如,第一介绍了NumPy的基本概念和常用数据类型,第二介绍了数组的创建和操作方法,第三介绍了数学函数和统计方法,以此类推。 手册中的每个主题都以简洁明了的方式进行介绍,并提供了示例代码和说明,方便用户理解和运用。它还包含了一些常见问题的解答和一些技巧和技巧,帮助用户更好地利用NumPy进行数据处理和分析。 对于初学者来说,这份中文手册是学习NumPy的宝贵资源。它提供了全面而详细的资料,帮助新手从基础到进阶快速上手NumPy。对于有经验的用户来说,手册也提供了一些高级的技巧和用法,帮助他们更好地掌握NumPy的核心功能和扩展模块。 总之,NumPy数据处理中文手册(chm)是一份包含丰富内容的中文文档,它涵盖了NumPy库的各种特性和用法,旨在帮助用户学习和使用NumPy进行数据处理。无论是初学者还是有经验的用户,都可以从中获得有益的知识和技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值