numpy速通

基本介绍:

Numpy 是一个用于创建和操作数组的 Python 库
矩阵 == python 列表 == numpy 数组 == pytorch 张量 == tensorflow 张量

导入 numpy

import numpy
"或"
import numpy as np

创建指定数组

np.array(指定的数组)

1. 一维数组

np.array 以创建一个包含指定值的一维 NumPy 数组

one_dimensional_array = np.array([1.2, 2.4, 3.5, 4.7, 6.1, 7.2, 8.3, 9.5])
print(one_dimensional_array)

输出:
[1.2 2.4 3.5 4.7 6.1 7.2 8.3 9.5]

2. 多维数组

np.array 以创建一个包含指定值的多维维 NumPy 数组,此时指定一个额外的方括号层

two_dimensional_array = np.array([[6, 5], [11, 7], [4, 8]])# 数组大小为三行二列
print(two_dimensional_array)

输出:
[[ 6 5]
[11 7]
[ 4 8]]

3. 数组拷贝

np.copy(arr)
arr = np.array([[6, 5], [11, 7], [4, 8]])
arr2 = np.copy(arr)    #    [[6, 5], [11, 7], [4, 8]]

数组填充

1. 填充为零数组 或单位数组

np.zeros(形状)
np.ones(形状)

1.1. 填充为一维数组:
np.zeros(len()) 或单位数组 np.ones(len())

>>> np.zeros(5)
"""零数组输出:"""
array([0., 0., 0., 0., 0.])

>>> np.ones(5)
"""单位数组输出:"""
array([1., 1., 1., 1., 1.])

1.2. 填充为二维数组
二维零数组或二维单位数组np.zeros(h , w) 或单位数组 np.ones(h , w)

matrix = np.zeros((3, 2))
print(matrix)

"""输出"""
[[0. 0.]
 [0. 0.]
 [0. 0.]]
matrix = np.zeros((3, 2))
print(matrix)

"""输出"""
[[1. 1.]
 [1. 1.]
 [1. 1.]]

括号里面的数字,3 代表行,2 代表列

1.3. 填充为三维数组
零数组np.zeros(c , h , w) 或单位数组 np.ones(c , h , w)
填充零数组和填充单位数组方式相同,以填充零数组为例

import numpy as np
# 创建一个 4x2x4 的三维数组
matrix = np.zeros((4, 2, 4))
# 打印数组的形状
print(matrix.shape)  # 输出:(4, 2, 4)
# 打印数组
print(matrix)

"""输出"""
[[[0. 0. 0. 0.]
  [0. 0. 0. 0.]]
 
 [[0. 0. 0. 0.]
  [0. 0. 0. 0.]]
 
 [[0. 0. 0. 0.]
  [0. 0. 0. 0.]]
 
 [[0. 0. 0. 0.]
  [0. 0. 0. 0.]]]
  • 第一个维度(4)表示深度(depth)。
  • 第二个维度(2)表示行数(rows)。
  • 第三个维度(4)表示列数(columns)。
    1.4. 填充为多维数组
    np.zeros(b , c , h , w) 或单位数组 np.ones(b , c , h , w)
import numpy as np
# 创建一个 2x2x3x2 的四维数组
array = np.zeros((2, 2, 3, 2))
# 打印数组的形状
print(array.shape)  # 输出:(2, 2, 3, 2)
# 打印数组
print(array)

"""输出结果"""
[[[[0. 0.]
   [0. 0.]
   [0. 0.]]

  [[0. 0.]
   [0. 0.]
   [0. 0.]]]


 [[[0. 0.]
   [0. 0.]
   [0. 0.]]

  [[0. 0.]
   [0. 0.]
   [0. 0.]]]]

如果以在进行图像处理时的张量距离的话,张量大小为(b , c , h , w)

  • 第一个维度 b的大小为 2。
  • 第二个维度 c的大小为 2。
  • 第三个维度 h的大小为 3。
  • 第四个维度 w的大小为 2。
    综上所述,当进行填充的时候,最后两维一直为高和宽的大小,这个可以类比到其他的不是填充的数组中去

2. 填充为数字序列

创建为有序一维数组

np.arange(start , stop , step)

示例:

sequence_of_integers = np.arange(5, 12)
print(sequence_of_integers)

"""输出,范围是[5,12) 步长默认为1"""
[ 5 6 7 8 9 10 11] # [5,12)
# 创建一个从 0 到 9 的一维数组
arr = np.arange(10)
print(arr)  # 输出: [0 1 2 3 4 5 6 7 8 9]

# 创建一个从 2 到 20,步长为 3 的一维数组
arr = np.arange(2, 21, 3)
print(arr)  # 输出: [ 2  5  8 11 14 17 20]

3. 填充为随机数组

3.1. 填充为随机整数数组

np.random.randint(low, high, size = (b , c , h , w))

说明

  • 生成指定范围内的随机整数
    参数介绍:
  • low:范围下限
  • high:范围上限,范围时右开区间
  • size:数组尺寸
    • 一维时:size=(n,)
    • 二维时:size = (h , w)
    • 三维时:size = (c , h , w)
    • 四维时:size = (b , c , h , w)
"""一维"""
random_integers_between_50_and_100 = np.random.randint(low=50, high=101, size=(6,))

print(random_integers_between_50_and_100)

"""输出"""
[81 81 99 59 53 86]
"""多维"""
np.random.randint(low=50, high=101, size=(3,2,3,2))
"""输出"""
array([[[[ 77,  75],
         [100,  95],
         [100,  99]],
        [[ 63,  96],
         [ 71,  61],
         [ 60,  93]]],


       [[[ 65,  90],
         [ 77,  75],
         [ 77,  74]],

        [[ 91,  75],
         [ 84,  78],
         [ 51,  66]]],


       [[[ 90,  68],
         [ 55,  99],
         [ 61,  78]],

        [[ 54,  91],
         [ 78,  69],
         [ 77,  52]]]])

3.2. 填充为随机浮点数(0-1)

np.random.random(size  =(b , c , h , w))

说明:

  • 用于创建介于 0.0 和 1.0 之间的随机浮点数

size:数组尺寸

  • 一维时:size=(n,)
  • 二维时:size = (h , w)
  • 三维时:size = (c , h , w)
  • 四维时:size = (b , c , h , w)
"""一维"""
random_floats_between_0_and_1 = np.random.random((6,))
print(random_floats_between_0_and_1)

"""输出"""
[0.96922576 0.15835409 0.55987845 0.94381404 0.08586431 0.11261668]
"""多维"""
np.random.random(size  = (2,2,3,2))

"""输出"""
array([[[[0.0290784 , 0.69311009],
         [0.06694433, 0.53714244],
         [0.52475364, 0.25343246]],

        [[0.15472061, 0.82163839],
         [0.16268672, 0.65971161],
         [0.68317785, 0.09745825]]],


       [[[0.90242123, 0.47122513],
         [0.51237921, 0.39516523],
         [0.53038891, 0.62569372]],

        [[0.59298034, 0.21678875],
         [0.31503332, 0.42422378],
         [0.20752558, 0.4096423 ]]]])

数组运算:

1. 广播机制

1.1. NumPy 广播机制 (Broadcasting)

对两个数组进行加法或减法运算,线性代数要求这两个操作数具有相同的维度。此外,对两个数组进行乘法运算,线性代数对操作数的维度兼容性施加了严格的规则。

NumPy 的广播 (Broadcasting) 机制是一种强大的功能,它允许 NumPy 在执行算术运算时处理形状不完全相同的数组。简单来说,广播机制会自动扩展两个进行运算的数组中,较小数组的形状,使其与较大数组的形状兼容,从而可以进行逐元素运算

1.1.1. 广播的规则

NumPy 在执行运算时,会比较两个数组的形状。如果满足以下条件之一,则可以进行广播:

  1. 数组具有相同的形状。
  2. 数组的维度数量不同,但较小数组的形状可以扩展到与较大数组的形状匹配。
  3. 数组的维度数量相同,但其中一个数组的某个维度的大小为 1。
    如果以上条件都不满足,NumPy 将抛出 ValueError 异常,提示数组形状不兼容。

1.1.2. 广播的步骤

  1. 维度对齐: NumPy 会从后向前比较数组的形状。如果两个数组的维度数量不同,NumPy 会在较小数组的形状前面补 1,使其维度数量与较大数组相同。
  2. 形状扩展: 对于形状中大小为 1 的维度,NumPy 会将其扩展到与另一个数组在该维度上的大小相同。这个过程不会复制数据,而是创建一个“视图”,指向原始数据。

1.2. 示例

1.2.1. 数组与标量相加

import numpy as np

a = np.array([1, 2, 3])
b = 2  # 标量

c = a + b  # 广播机制将标量 b 扩展为 [2, 2, 2]
print(c)  # 输出: [3 4 5]

在这个例子中,标量 b 被广播成与数组 a 相同的形状 (3,),然后进行逐元素相加。

1.2.2. 一维数组与二维数组相加

import numpy as np

a = np.array([[1, 2, 3],
              [4, 5, 6]])  # 形状为 (2, 3)
b = np.array([10, 20, 30])  # 形状为 (3,)

c = a + b  # 广播机制将 b 扩展为 [[10, 20, 30], [10, 20, 30]]
print(c)  #输出:[[11 22 33],
 		#       [14 25 36]]

在这个例子中,一维数组 b 被广播成与二维数组 a 相同的形状 (2, 3),然后进行逐元素相加。

1.2.3. 形状不兼容的例子

import numpy as np

a = np.array([[1, 2, 3],
              [4, 5, 6]])  # 形状为 (2, 3)
b = np.array([10, 20])  # 形状为 (2,)

try:
    c = a + b
except ValueError as e:
    print(e)  # 输出: operands could not be broadcast together with shapes (2,3) (2,)

在这个例子中,数组 a 的形状为 (2, 3),数组 b 的形状为 (2,)。由于 b 无法广播成与 a 相同的形状,NumPy 抛出了 ValueError 异常。

1.3. 广播的优势

  • 简化代码: 广播机制可以避免显式地复制数据,从而简化代码。
  • 提高效率: 广播机制通常比显式复制数据更高效,因为它避免了不必要的数据复制操作。
  • 灵活性: 广播机制允许 NumPy 处理形状不完全相同的数组,从而提高了代码的灵活性。

2. 数组加减

"""多维整数数组"""
np.random.randint(low = 2, high = 10+1 , size = (1 , 2, 2 , 2)) + 2# 生成范围为[2,10] 尺寸为1*2*2*2,然后整体+2
"""输出"""
array([[[[5, 5],
         [8, 6]],

        [[4, 8],
         [5, 4]]]]) #原矩阵
         
array([[[[7, 7],
         [10, 8]],

        [[6, 10],
         [7, 6]]]])#运算后矩阵

减法等同

3. 多维数组加减

多维数组的加减运算在 NumPy 中非常直观,并且遵循一些重要的规则,特别是关于广播机制。

3.1. 逐元素加减

最常见的加减运算是逐元素的,这意味着数组中对应位置的元素会进行加减操作。

  • 加法: 使用 + 运算符或 np.add() 函数。
  • 减法: 使用 - 运算符或 np.subtract() 函数。
import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

# 加法
c = a + b  # 或 c = np.add(a, b)
print("加法结果:\n", c)

# 减法
d = a - b  # 或 d = np.subtract(a, b)
print("减法结果:\n", d)

# 加法结果:
 # [[ 6  8]
 # [10 12]]
# 减法结果:
 # [[-4 -4]
 # [-4 -4]]

3.2. 广播机制加减形状不完全相同的数组

当进行加减运算的数组形状不完全相同时,NumPy 会尝试应用广播机制。广播机制允许 NumPy 在某些情况下对形状不兼容的数组进行运算。

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])  # 形状为 (2, 3)
b = np.array([10, 20, 30])  # 形状为 (3,)

# 加法,b 会被广播成 [[10, 20, 30], [10, 20, 30]]
c = a + b
print("广播加法结果:\n", c)

a = np.array([[1, 2], [3, 4]])  # 形状为 (2, 2)
b = np.array([10, 20])  # 形状为 (2,)

# 减法,b 会被广播成 [[10, 20], [10, 20]]
d = a - b
print("广播减法结果:\n", d)

# 广播加法结果:
 # [[11 22 33]
 # [14 25 36]]
# 广播减法结果:
 # [[-9 -18]
 # [-7 -16]]

3.3. 注意事项

  • 确保数组的数据类型兼容,否则可能会发生类型转换,导致精度损失。
  • 理解广播机制对于处理形状不完全相同的数组至关重要。
  • 如果数组的形状不兼容,并且无法通过广播机制进行运算,NumPy 会抛出 ValueError 异常。

4. 数组乘除:

"""多维整数数组"""
np.random.randint(low = 2, high = 10+1 , size = (1 , 2, 2 , 2)) * [2,3]# 生成范围为[2,10] 尺寸为1*2*2*2,然后整体+2
"""输出"""
array([[[[10,  8],
         [10,  6]],

        [[ 6, 10],
         [ 4, 10]]]])#原矩阵
         
array([[[[20, 24],
         [20, 18]],

        [[12, 30],
         [ 8, 30]]]])#运算后矩阵

除法等同

5. 多维数组乘法

多维数组的乘除运算在 NumPy 中同样非常灵活,并且与加减运算类似,也遵循广播机制。

5.1. 逐元素乘除

数组中对应位置的元素会进行乘除操作。

(np.multiply()或*) # 乘
(np.divide() 或 /)#  除
import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

# 乘法
c = a * b  # 或 c = np.multiply(a, b)
print("乘法结果:\n", c)

# 除法
d = a / b  # 或 d = np.divide(a, b)
print("除法结果:\n", d)

'''输出:'''
# 乘法结果:
 # [[ 5 12]
 # [21 32]]
# 除法结果:
 # [[0.2        0.33333333]
 # [0.42857143 0.5       ]]

其他除法:

  • np.floor_divide(x1, x2): 返回 (x1 // x2) 的结果,即向下取整的除法。
  • np.trunc(x): 返回数组的截断整数部分。
  • np.remainder(x1, x2)np.mod(x1, x2): 返回除法的余数。

5.1.1. 广播机制运算形状不完全相同的数组

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])  # 形状为 (2, 3)
b = np.array([10, 20, 30])  # 形状为 (3,)

# 乘法,b 会被广播成 [[10, 20, 30], [10, 20, 30]]
c = a * b
print("广播乘法结果:\n", c)

a = np.array([[1, 2], [3, 4]])  # 形状为 (2, 2)
b = np.array([10, 20])  # 形状为 (2,)

# 除法,b 会被广播成 [[10, 20], [10, 20]]
d = a / b
print("广播除法结果:\n", d)


"""输出:"""
	广播乘法结果:
	[[ 10  40  90]
	[ 40 100 180]]
	广播除法结果:
	[[0.1        0.1       ]
	[0.3        0.2       ]]

5.2. 矩阵乘法

np.matmul(a , b)
  • 如果 a 和 b 都是二维数组,则执行标准的矩阵乘法。
  • 如果 a 或 b 中有一个是标量,则将其视为一个 1x1 的矩阵。
  • 如果 a 是 N 维数组,b 是 M 维数组,则将 a 的最后两个轴和 b 的最后两个轴视为矩阵,执行批量矩阵乘法。此时 a 的最后一个轴与 b 的倒数第二个轴对齐,其他轴需要满足广播规则。

使用 @ 运算符或 np.matmul() 函数,进行矩阵乘法。要求第一个数组的列数等于第二个数组的行数。

import numpy as np

a = np.array([[1, 2], [3, 4]])  # 形状为 (2, 2)
b = np.array([[5, 6], [7, 8]])  # 形状为 (2, 2)

c = a @ b  # 或 c = np.matmul(a, b)
print(c)

'''输出:'''
[[19 22]
 [43 50]]
"""三维数组与二维数组的矩阵乘法"""
import numpy as np

a = np.arange(12).reshape((2, 3, 2))  # 形状为 (2, 3, 2)
b = np.array([[1, 2], [3, 4], [5, 6]])  # 形状为 (3, 2)

# 矩阵乘法,a 的最后两个轴 (3, 2) 与 b 的前两个轴 (3, 2) 进行矩阵乘法
c = np.matmul(a, b.T)
print("结果:\n", c)
print("结果的形状:", c.shape)


# array([[[  2,   4,   6],
        # [  8,  18,  28],
        # [ 14,  32,  50]],

       # [[ 20,  46,  72],
        # [ 26,  60,  94],
        # [ 32,  74, 116]]])
# 形状: (2, 3, 3)

5.3. 点积

np.dot(a , b)

使用 np.dot() 函数,可以进行向量点积、矩阵乘法以及更高维度的数组乘法。

  • 如果 a 和 b 都是一维数组,则计算它们的点积(内积)。
  • 如果 a 和 b 都是二维数组,则执行矩阵乘法。
  • 如果 a 是 N 维数组,b 是 M 维数组,如果 N > 1 且 M > 1,则 a 的最后一个轴和 b 的倒数第二个轴进行对齐,然后保留其他轴形状大小

向量点积:

import numpy as np

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

c = np.dot(a, b)
print(c)  # 输出: 32 (1*4 + 2*5 + 3*6)

矩阵乘法: 与 @ 运算符和 np.matmul() 函数效果相同。

"""形状相同"""
import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

c = np.dot(a, b)
print(c)

"""输出:"""

[[19 22]
 [43 50]]
"""二维数组与一维数组的点乘"""
import numpy as np

a = np.array([[1, 2], [3, 4]])  # 形状为 (2, 2)
b = np.array([5, 6])  # 形状为 (2,)

# 点乘,b 会被广播成 [5, 6]
c = np.dot(a, b)
print("结果:\n", c)  #结果: [17 39]
"""**三维数组与二维数组相乘**"""
import numpy as np

a = np.arange(24).reshape((2, 3, 4))  # 形状为 (2, 3, 4)
b = np.arange(8).reshape((4, 2))  # 形状为 (4, 2)

c = np.dot(a, b)
print("结果的形状:", c.shape)  # 输出: (2, 3, 2)

"""相乘结果"""
# array([[[ 28,  34],
        # [ 76,  98],
        # [124, 162]],

       # [[172, 226],
        # [220, 290],
        # [268, 354]]])

5.4. np.tensordot(a , b , axes) 函数

np.tensordot(a, b, axes)

参数说明:

  • a 和 b: 需要进行张量点积运算的两个数组。
  • axes: 指定在哪些轴上进行求和。它可以是:
    • 一个整数:表示 a 的最后 axes 个轴和 b 的最开始 axes 个轴进行求和。
    • 一个包含两个序列的列表或元组:第一个序列指定 a 中用于求和的轴,第二个序列指定 b 中用于求和的轴。这两个序列必须包含相同数量的轴。

工作原理:

  1. 确定求和轴: 根据 axes 参数确定 a 和 b 中用于求和的轴。
  2. 计算乘积: 将 a 和 b 中对应元素相乘。
  3. 求和: 沿着指定的轴对乘积结果进行求和。
  4. 重塑数组: 将结果数组的形状进行调整,使其成为一个合适的张量。

注意:
"求和" 是指沿着指定的轴进行缩并 (contraction) 操作,这实际上包含了乘法和加法两个步骤,最终效果是降低了结果张量的维度。先对应元素相乘,再相加

import numpy as np

a = np.arange(24).reshape((3, 4, 2))
b = np.arange(32).reshape((4, 2, 4))

c = np.tensordot(a, b, axes=([1, 2], [0, 1]))
print(c.shape)  # 输出: (3, 4)

在这个例子中,axes=([1, 2], [0, 1]) 指定了 a 的轴 1 和轴 2 (形状为 (4, 2)) 与 b 的轴 0 和轴 1 (形状为 (4, 2)) 进行对齐求和。

5.5. np.dot()和np.matmul()的区别

一维数组的乘法

  • 对于一维数组,np.dot() 和 np.matmul() 的行为也相同,都计算两个数组的内积(点积)。

二维数组的乘法

  • 对于二维数组,np.dot() 和 np.matmul() 的行为相同,都执行标准的矩阵乘法.
    高维数组的乘法 (核心区别)

对于维度大于 2 的数组,np.dot() 和 np.matmul() 的行为开始出现差异。

  • np.dot(a, b):
    • 如果 a 是 N 维数组,b 是 M 维数组,且 N > 1 且 M > 1,则 np.dot() 会将 a 的最后一个轴和 b 的倒数第二个轴进行点积运算。 其余轴将根据广播规则进行扩展。 这可能导致结果的形状与预期不符。
  • np.matmul(a, b) 或 a @ b:
    • 如果 a 是 N 维数组,b 是 M 维数组,且 N > 1 且 M > 1,则 np.matmul() 会将 a 和 b 的最后两个维度视为矩阵进行乘法运算。其余维度将被视为批量维度,并进行广播。这更符合矩阵乘法的直观理解
import numpy as np

a = np.arange(24).reshape((2, 3, 4))
b = np.arange(12).reshape((4, 3))

c = np.dot(a, b)
print("np.dot() 结果形状:", c.shape)  # 输出: (2, 3, 3)

d = np.matmul(a, b)
print("np.matmul() 结果形状:", d.shape)  # 输出: (2, 3, 3)
场景 np.dot()行为 np.matmul()行为
二维数组 等价于矩阵乘法 等价于矩阵乘法
一维数组 返回标量(点积) 报错(需转为二维)
三维数组 最后一个轴与倒数第二个轴对齐,其他广播 最后两个轴进行矩阵乘法,其他轴需匹配或广播
标量输入 直接相乘(标量相乘) 报错(标量不能参与矩阵乘法)
特性 np.dot() np.matmul()
设计目的 计算向量点积或矩阵乘法(灵活) 严格执行矩阵乘法(线性代数规则)
对一维数组 支持(返回标量点积) 不支持(需转为二维)
高维数组处理 最后一个轴与倒数第二个轴对齐,广播其他轴 最后两个轴执行矩阵乘法,其他轴需匹配或广播
与 @ 运算符关系 二维时等价于@ 完全等价于@

6. 注意事项

  • 确保数组的数据类型兼容,否则可能会发生类型转换,导致精度损失。
  • 除法运算要避免除以 0,否则会产生 inf (无穷大) 或 NaN (Not a Number)。
  • 矩阵的除法是点乘逆矩阵
  • 理解广播机制对于处理形状不完全相同的数组至关重要。
  • 二者的维度可以不一样多(如三维和一维的进行运算),但是二者每一维的维度必须匹配(如三维的列维度大小必须和一维大小相同)
  • 如果数组的形状不兼容,并且无法通过广播机制进行运算,NumPy 会抛出 ValueError 异常。

形状与统计

  • 按维度(指定 axis,0,1,2 依次按照最外层维度到最内层维度)
  • keepdims=True 的作用keepdims=True 参数会保留被约简的维度,使其大小变为 1。 这在进行广播运算时非常有用,可以避免形状不匹配的错误。

先创建一个 Generator

import numpy as np
rng = np.random.default_rng(seed=42)

再生成一个均匀分布

arr = rng.uniform(0, 1, (2, 3, 2))
arr

"""输出"""
array([[[0.64386512, 0.82276161],
		[0.4434142 , 0.22723872],
		[0.55458479, 0.06381726]],
		
		[[0.82763117, 0.6316644 ],
		[0.75808774, 0.35452597],
		[0.97069802, 0.89312112]]])

1. 形状

1.1. 尺寸

arr.shape
arr.shape   # (2, 3, 2),两通道,三行二列

1.2. 数据量

arr.size   # 12, 总共十二个数据量

1.3. 形状打平

多维数组变为一维数组:arr.ravel()

arr.ravel()

array([0.64386512, 0.82276161, 0.4434142 , 0.22723872, 0.55458479,
       0.06381726, 0.82763117, 0.6316644 , 0.75808774, 0.35452597,
       0.97069802, 0.89312112])

1.4. 维度扩展

np.expand_dims(arr , axis =   )

说明:

  • 用于在指定轴上扩展数组维度的函数。
    参数:
  • arr:要扩展的数组
  • axis :扩展的是第几维的维度
    注意:
  • 在进行扩充时,如果当前维度存在,则添加的前提下当前维度与后面的维度被新添加的维度嵌套在内层.
  • 在进行扩充时,维度不能时跳跃的,比如 arr 的形状为(2,3,2),其维度为 0,1,2,那么在扩充时,axis 可以为 0,1,2,3;但是 axis 不能是大于 3。
arr.shape    # (2,3,2)
np.expand_dims(arr, axis = 1).shape   #  (2, 1, 3, 2)
np.expand_dims(arr, axis=(1, 3, 4)).shape   #  (2, 1, 3, 1, 1, 2)
>>> np.expand_dims(arr, axis = 4).shape

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "y", line 597, in expand_dims
    axis = normalize_axis_tuple(axis, out_ndim)
  File "y", line 1380, in normalize_axis_tuple
    axis = tuple([normalize_axis_index(ax, ndim, argname) for ax in axis])
  File "y", line 1380, in <listcomp>
    axis = tuple([normalize_axis_index(ax, ndim, argname) for ax in axis])
numpy.exceptions.AxisError: axis 4 is out of bounds for array of dimension 4

1.5. 维度去除

 np.squeeze(arr  ,  axis =  )

说明:

  • 用于去除数组中大小为 1 的 维度的函数。axis 参数用于指定要压缩的轴(即要移除的大小为 1 的维度)。
    参数:
  • arr:要扩展的数组
  • axis :可选参数,指定要压缩的轴。如果 None,则会压缩所有大小为 1 的维度
    返回值:
  • 返回一个数组,其大小为 1 的维度被移除。
arr.shape # (2, 3, 2)
np.squeeze(arr,axis=1)  # 这里会报错,因为在arr中,第2个维度大小不为1
expand  = np.expand_dims(arr , axis = 1	)  # (2, 1, 3, 2)
np.squeeze(expand,axis=1)  #(2, 3, 2)
expand  = np.expand_dims(arr, axis=(1, 3, 4)).shape   #  (2, 1, 3, 1, 1, 2)
np.squeeze(expand, axis = None)  #(2, 3, 2)

1.6. 形状修改:

arr.reshape(new_shape)

说明:

  • 用于将数组重新塑形为一个新的数组,而不改变元素的总数。通过指定新的形状,可以灵活地调整数组的维度,以满足不同的计算需求。
    参数:
  • new_shape: 新的形状,可以是整数元组或整数列表。例如,(2, 3) 表示一个 2 行 3 列的二维数组
    注意事项:
  • 原数组和新的数组的元素个数必须相同
arr.shape # (2, 3, 2)
arr.reshape(1, 3, 4).shape   # (1, 3, 4)

可以偷懒,使用 -1 表示其他维度(此处 -1 为 3),注意,reshape 参数可以是 tuple 或连续整数

arr.reshape((4, -1)).shape  # (4, 3)

1.7. 形状重塑

arr.resize(new_shape)

说明:

  • resize 方法用于改变数组的形状和大小。与 reshape 方法不同,resize 方法会直接修改原始数组,并且可以改变数组的大小
    参数:
  • new_shape: 新的形状,可以是整数元组或整数列表
    注意事项:
  • 直接修改原始数组
  • 不能用-1
  • resize 不一定和原来的元素数量一样多
arr2 = np.array([[[1, 2],[3, 4],[5, 6]],[[1, 2],[3, 4],[5, 6]]])
arr2.shape # (2, 3, 2)
arr2.resize(1, 3, 4)
arr2.shape    # (1, 3, 4)

arr2.resize(1, 2, 4)
arr2.shape  #  (1, 2, 4) 可见,元素数量变少 array([[[1, 2, 3, 4],[5, 6, 1, 2]]]),去除了末尾的一个维度

"""如果想保证之前数组不变,可以采用copy的操作"""
arr2copy = np.copy(arr2)
arr2copy.resize(2,3,2)  
arr2.shape     #  (1, 2, 4)   array([[[1, 2, 3, 4],[5, 6, 1, 2]]])
arr2copy.shape  
# (2,3,2)    array([[[1, 2],[3, 4],[5, 6]],[[1, 2],[0, 0],[0, 0]]])  维度不够时用零填充

# 如果用 np.resize 会略有不同
# 元素数量不够时,会自动复制
np.resize(arr2, (5, 3)) 

array([[1, 2, 3],
       [4, 5, 6],
       [1, 2, 1],
       [2, 3, 4],
       [5, 6, 1]])

1.8. 转置

arr.T
np.transpose(arr,() )

说明:

  • arr.T 适用于简单的一维和二维数组转置。
  • np.transpose(arr) 更加通用,可以处理任意维度的数组,并且可以指定轴的顺序。
    参数:
  • arr:转置的数组
  • () :可选参数,指定转置的轴,如原始数组的轴顺序从 (0, 1, 2) 变为 (1, 0, 2)。如果 None,则会转置整个矩阵(也就是将整个维度反过来,(0, 1, 2) 变为 (2, 1, 0))
# 一维
np.array([1,2]).T.shape  # (2,) 转置之后还是自己
# 二维
arr3 = np.array([[1, 2, 3], [4, 5, 6]])  #(2,3)  [[1, 2, 3], [4, 5, 6]]
arr3.T     # (3,2)     array[[1, 4],  [2 ,5],  [3, 6]]
np.transpose(arr3)     # (3,2)     array[[1, 4],  [2 ,5],  [3, 6]]
# 高维:
arr3 = np.copy(arr)   # (2, 3, 2)
arr3.reshape(1,3,4)   # (1,3,4) 
# array([[[0.64386512, 0.82276161, 0.4434142 , 0.22723872],
#         [0.55458479, 0.06381726, 0.82763117, 0.6316644 ],
#         [0.75808774, 0.35452597, 0.97069802, 0.89312112]]])
np.transpose(arr3)     # (4, 3, 1) 
# array([[[0.64386512],
#         [0.55458479],
#         [0.75808774]],
# 
#        [[0.82276161],
#         [0.06381726],
#         [0.35452597]],
# 
#        [[0.4434142 ],
#         [0.82763117],
#         [0.97069802]],

#        [[0.22723872],
#         [0.6316644 ],
#         [0.89312112]]])
np.transpose(arr3, (0,2,1))  # (1, 4, 3)
# array([[[0.64386512, 0.55458479, 0.75808774],
#         [0.82276161, 0.06381726, 0.35452597],
#         [0.4434142 , 0.82763117, 0.97069802],
#         [0.22723872, 0.6316644 , 0.89312112]]])

#更高维度:比如4维
>>> arr4 = np.arange(24).reshape(1,4,3,2)
>>> arr4
# array([[[[ 0,  1],
         # [ 2,  3],
         # [ 4,  5]],

        # [[ 6,  7],
         # [ 8,  9],
         # [10, 11]],

        # [[12, 13],
         # [14, 15],
         # [16, 17]],

        # [[18, 19],
         # [20, 21],
         # [22, 23]]]])
>>> np.transpose(arr4)
# array([[[[ 0],
         # [ 6],
         # [12],
         # [18]],

        # [[ 2],
         # [ 8],
         # [14],
         # [20]],

        # [[ 4],
         # [10],
         # [16],
         # [22]]],


       # [[[ 1],
         # [ 7],
         # [13],
         # [19]],

        # [[ 3],
         # [ 9],
         # [15],
         # [21]],

        # [[ 5],
         # [11],
         # [17],
         # [23]]]])
>>> np.transpose(arr4).shape
(2, 3, 4, 1)

2. 最大、最小、中位、分位值

arr.max()   # 所有数据中的最大值  0.97069802
arr.min()   # 所有数据中的最小值  0.06381726
np.median(arr)   #所有数据中的中位数  0.63776476
np.quantile(arr, q=0.25)   # 分位数,所有数据中的1/4   0.4211921425 q为分位值

下面讲解 axis 的作用,以 np.max()为例, np.min,np.median(arr),np.quantile(arr, q=0.25) 同理

arr.max(axis=0)   # 沿着三维数组 `arr` 的最外层维度(`axis=0`)查找最大值,并返回一个形状为 `(3, 2)` 的二维数组,其中每个元素都是沿着 `axis=0` 的最大值。
arr.max(axis=1)   # 沿着三维数组 `arr` 的第二层层维度(`axis=1`)查找最大值,并返回一个形状为 `(2, 2)` 的二维数组,其中每个元素都是沿着 `axis=1` 的最大值。
arr.max(axis=2)   # 沿着三维数组 `arr` 的第三层层维度(`axis=2`)查找最大值,并返回一个形状为 `(2, 3)` 的二维数组,其中每个元素都是沿着 `axis=2` 的最大值。

按照 keepdims=True 保证整体维度个数不变
举例:
image.png

3. 平均值、累计求和、方差、标准差

3.1. 平均值

np.average(arr, axis=None, weights=None, returned=False)

说明

  • 用于计算数组的加权平均值。它可以沿着指定的轴计算平均值,并且可以根据权重进行加权平均。

参数说明

  • arr : 输入数组。
  • axis: 可选参数,指定计算哪个轴的平均值。默认情况下,axis=None,表示计算整个数组的平均值。
  • weights: 可选参数,指定与 a 中的元素关联的权重。weights 数组的形状必须与 a 相同,或者可以广播到 a 的形状。
  • returned: 可选参数,如果为 True,则返回平均值和权重的和。默认为 False

注意事项:

  • 如果没有提供 weights 参数,则计算简单平均值。
  • weights 数组的形状必须与 a 相同,或者可以广播到 a 的形状。
  • 如果 returned 参数为 True,则返回平均值和权重的和。
arr   # (2,3,2)
array([[[0.64386512, 0.82276161],
        [0.4434142 , 0.22723872],
        [0.55458479, 0.06381726]],

       [[0.82763117, 0.6316644 ],
        [0.75808774, 0.35452597],
        [0.97069802, 0.89312112]]])

"""计算整个数组的平均值"""
np.average(arr)   # 0.5992841766666667
"""**计算指定的轴的平均值**"""
np.average(arr, axis=0)   #  计算维度的平均值
# array([[0.73574814, 0.72721301],
#        [0.60075097, 0.29088234],
#        [0.76264141, 0.47846919]])
np.average(arr, axis=1)  # 对于每一个维度,计算每一行的平均值
# array([[0.54728804, 0.37127253],
#        [0.85213898, 0.62643716]])
"""**使用权重计算加权平均值**"""
weights = np.arange(0,1,1/12).reshape(2,3,2)
# array([[[0.        , 0.08333333],
#         [0.16666667, 0.25      ],
#          [0.33333333, 0.41666667]],

#        [[0.5       , 0.58333333],
#         [0.66666667, 0.75      ],
#         [0.83333333, 0.91666667]]])
np.average(arr, weights=weights)  # 0.6530745093939394

np.average(arr, axis = 0, weights=weights)
# array([[0.82763117, 0.65555155],
#        [0.69515303, 0.32270416],
#        [0.85180853, 0.63396366]])
"""**返回平均值和权重的和**"""
np.average(arr, weights=weights, returned=True)  # (0.6530745093939394, 5.5),第一个元素是数组平均值,第二个元素是权重之和

3.2. 求和

np.sum(a, axis=None, dtype=None, out=None, keepdims=, initial=, where= )

说明:
用于计算数组元素的总和。它可以沿着指定的轴计算总和,也可以计算整个数组的总和。

参数:

  • a: 输入数组。
  • axis: 可选参数,指定沿着哪个轴计算总和。默认情况下,axis=None,表示计算整个数组的总和。
  • dtype: 可选参数,指定返回数组的类型。
  • out: 可选参数,指定将结果放入哪个数组中。
  • keepdims: 可选参数,如果设置为 True,则结果将保持与 a 相同的维度。[True, False]
  • initial: 可选参数,总和的起始值。
  • where: 可选参数,用于指定哪些元素参与求和,[True, False]

注意事项:

  • 实际上,用法与求平均相同
arr   # (2,3,2)
array([[[0.64386512, 0.82276161],
        [0.4434142 , 0.22723872],
        [0.55458479, 0.06381726]],

       [[0.82763117, 0.6316644 ],
        [0.75808774, 0.35452597],
        [0.97069802, 0.89312112]]])
"""直接求和"""
np.sum(arr)  #  7.1914101200000005
np.sum(arr,keepdims = True)  # array([[[7.19141012]]])

np.sum(arr,keepdims = True).shape  # (1, 1, 1)

"""按照维度求和"""
np.sum(arr, axis=0)  # (3,2)
# array([[1.47149629, 1.45442601],
#        [1.20150194, 0.58176469],
#        [1.52528281, 0.95693838]])
np.sum(arr, axis=0,keepdims  =True)
# array([[[1.47149629, 1.45442601],
#         [1.20150194, 0.58176469],
#         [1.52528281, 0.95693838]]])
np.sum(arr, axis=0,keepdims  =True).shape   # (1, 3, 2)

np.sum(arr, axis=1)
# array([[1.64186411, 1.11381759],
#        [2.55641693, 1.87931149]])

3.3. 标准差

np.std(arr, axis=None, dtype=None, out=None, ddof=0, keepdims=, where=)

说明:

  • 用于计算数组元素的标准差。标准差是衡量数据集中数据分散程度的一种方法。
    参数介绍:
  • arr: 输入数组。
  • axis: 可选参数,指定沿着哪个轴计算标准差。默认情况下,axis=None,表示计算整个数组的标准差。
  • dtype: 可选参数,指定计算标准差时使用的类型。
  • out: 可选参数,指定将结果放入哪个数组中。
  • ddof: 可选参数,表示自由度。ddof=0 表示总体标准差,ddof=1 表示样本标准差。默认为 0
  • keepdims: 可选参数,如果设置为 True,则结果将保持与 a 相同的维度。
  • where: 可选参数,用于指定哪些元素参与计算标准差。

注意事项:

  • 主要使用的参数就是 arr 和 axis
  • 使用方法与求平均值和求和相同

3.4. 方差

np.var(arr, axis=None, dtype=None, out=None, ddof=0, keepdims=, where=)

说明:

  • 用于计算数组元素的方差。方差是衡量数据集中数据分散程度的一种方法,表示数据偏离平均值的程度。
    参数介绍:
  • arr: 输入数组。
  • axis: 可选参数,指定沿着哪个轴计算标准差。默认情况下,axis=None,表示计算整个数组的标准差。
  • dtype: 可选参数,指定计算标准差时使用的类型。
  • out: 可选参数,指定将结果放入哪个数组中。
  • ddof: 可选参数,表示自由度。ddof=0 表示总体标准差,ddof=1 表示样本标准差。默认为 0
  • keepdims: 可选参数,如果设置为 True,则结果将保持与 a 相同的维度。
  • where: 可选参数,用于指定哪些元素参与计算标准差。

注意事项:

  • 主要使用的参数就是 arr 和 axis
  • 使用方法与求平均值和求和相同

数组切片与索引:

arr[start:stop:step]

说明:

  • 切片和索引是通过对已有 array 进行操作而得到想要的「部分」元素的行为过程。其核心动作可以概括为:按维度根据 start:stop:step 操作 array。
  • 分为基本索引、切片、布尔索引、花式索引和修改数组元素
  • 核心是把数组的处理按维度分开,不处理的维度统一用 : 或 ... 代替;在操作时,首先关注「 , 」在哪里。
  • 索引支持负数,即从后往前索引。

参数说明:

  1. 冒号 (😃:用于创建切片对象,选择指定范围内的元素。

    • 基本用法
      • arr[start:stop]:选择从索引 start 开始到索引 stop 结束(不包括 stop)的元素。
      • arr[start:]:选择从索引 start 开始到数组末尾的所有元素。
      • arr[:stop]:选择从数组开头到索引 stop 结束(不包括 stop)的所有元素。
      • arr[:]:选择所有元素。
    • 指定步长
      • arr[start:stop:step]:选择从索引 start 开始到索引 stop 结束(不包括 stop)的元素,步长为 step
    • 多维数组
      • 在多维数组中,可以为每个维度指定切片。例如,arr[row_start:row_stop, col_start:col_stop]
  2. 省略号 (...):用于表示剩余的维度,简化高维数组的切片操作。

    • arr[i, ...]:表示选择索引 i 对应的元素,并包含剩余维度的所有元素。
    • arr[..., j]:表示选择索引 j 对应的元素,并包含之前维度的所有元素。
  3. 负数:用于从数组的末尾开始索引。反转

    • 基本用法
      • arr[-1]:表示数组的最后一个元素。
      • arr[-n]:表示数组的倒数第 n 个元素。
    • 切片中的负数
      • arr[:-1]:表示选择除最后一个元素外的所有元素。
      • arr[-3:]:表示选择最后三个元素。
      • arr[::-1]:表示反转数组。
  4. 逗号 (,):用于分隔不同维度的索引或切片。

    • arr[i, j]:表示选择二维数组中第 i 行第 j 列的元素。
    • arr[i:k, j:l]:表示选择二维数组中第 i 行到第 k-1 行,以及第 j 列到第 l-1 列的元素。

1. 基本索引

  • 一维数组

    import numpy as np
    
    arr = np.array([1, 2, 3, 4, 5])
    print(arr[0])  # 输出:1
    print(arr[3])  # 输出:4
    print(arr[-1]) # 输出:5 (最后一个元素)
    
  • 二维数组

    arr = np.array([[1, 2, 3],
                    [4, 5, 6],
                    [7, 8, 9]])
    print(arr[0, 0])  # 输出:1 (第一行第一列)
    print(arr[1, 2])  # 输出:6 (第二行第三列)
    print(arr[-1, -1]) # 输出:9 (最后一行最后一列)
    

2. 切片

  • 一维数组

    arr = np.array([1, 2, 3, 4, 5])
    print(arr[1:4])   # 输出:[2 3 4] (从索引 1 到 3)
    print(arr[:3])    # 输出:[1 2 3] (从索引 0 到 2)
    print(arr[2:])    # 输出:[3 4 5] (从索引 2 到结束)
    print(arr[:])     # 输出:[1 2 3 4 5] (所有元素)
    print(arr[1:5:2]) # 输出:[2 4] (从索引 1 到 4,步长为 2)
    print(arr[::-1])  # 输出:[5 4 3 2 1] (反转数组)
    
  • 二维数组

    arr = np.array([[1, 2, 3],
                    [4, 5, 6],
                    [7, 8, 9]])
    print(arr[0:2, 1:3])  # 注意范围是开区间
    # 输出:
    # [[2 3]
    #  [5 6]]
    # (选取第 0 行和第 1 行,以及第 1 列和第 2 列,交叉的部分)
    
    print(arr[:, 0])
    # 输出:[1 4 7] (选取所有行的第 0 列)
    
    print(arr[1, :])
    # 输出:[4 5 6] (选取第 1 行的所有列)
    
    print(arr[::2, ::2])
    # 输出:
    # [[1 3]
    #  [7 9]]
    # (选取行和列,步长都为 2)
    

3. 高维数组的切片和索引

  • 三维数组

    arr = np.arange(24).reshape((2, 3, 4))
    print("原始数组:")
    print(arr)
    # 输出:
    # [[[ 0  1  2  3]
    #   [ 4  5  6  7]
    #   [ 8  9 10 11]]
    #
    #  [[12 13 14 15]
    #   [16 17 18 19]
    #   [20 21 22 23]]]
    
    print("访问单个元素:")
    print(arr[0, 1, 2])  # 输出:6 (第一个块,第二行,第三列)
    print(arr[1, 2, 3])  # 输出:23 (第二个块,第三行,第四列)
    
    print("选取一个块:")
    print(arr[0, :, :])
    # 输出:
    # [[ 0  1  2  3]
    #  [ 4  5  6  7]
    #  [ 8  9 10 11]]
    # (第一个块的所有行和所有列)
    
    print("选取一个块的某几行和列:")
    print(arr[0, 0:2, 0:2])
    # 输出:
    # [[0 1]
    #  [4 5]]
    # (第一个块的前两行和前两列)
    
    print("选取所有块的某一行:")
    print(arr[:, 1, :])
    # 输出:
    # [[ 4  5  6  7]
    #  [16 17 18 19]]
    # (所有块的第二行)
    
    print("选取所有块的某一列:")
    print(arr[:, :, 2])
    # 输出:
    # [[ 2  6 10]
    #  [14 18 22]]
    # (所有块的第三列)
    
  • 四维数组

    arr = np.arange(48).reshape((2, 2, 3, 4))
    print("原始数组:")
    print(arr)
    # 输出:
    # [[[[ 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]]]]
    
    print("选取一个子数组:")
    print(arr[0, 1, :, :])
    # 输出:
    # [[12 13 14 15]
    #  [16 17 18 19]
    #  [20 21 22 23]]
    # (第一个大块的第二个小块的所有行所有列)
    
    print("选取所有大块的第一个小块的第二行的所有列:")
    print(arr[:, 0, 1, :])
    # 输出:
    # [[ 4  5  6  7]
    #  [28 29 30 31]]
    
    print("选取所有大块中的每一个第一个小块的所有行的第一列:")
    print(arr[:, 0, :, 0])
    # 输出:
    # [[ 0  4  8]
    #  [24 28 32]]
    
  • 使用省略号 (...)

  arr = np.arange(24).reshape((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]]]
  print("使用省略号选取第一个块:")
  print(arr[0, ...])
  # 输出:
  # [[ 0  1  2  3]
  #  [ 4  5  6  7]
  #  [ 8  9 10 11]]
  # (等价于 arr[0, :, :])

  print("使用省略号选取所有块的第二行:")
  print(arr[:, 1, ...])
  # 输出:
  # [[ 4  5  6  7]
  #  [16 17 18 19]]
  # (等价于 arr[:, 1, :])

4. 布尔索引

使用布尔数组来选择数组中的元素。[True, False]

arr = np.array([1, 2, 3, 4, 5])
bool_arr = np.array([True, False, True, False, True])
print(arr[bool_arr])  # 输出:[1 3 5]
arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
bool_arr = np.array([[True, False, True],
                     [False, True, False],
                     [True, False, True]])
print(arr[bool_arr])  # 输出:[1 3 5 7 9]

5. 花式索引

使用整数数组来选择数组中的元素。

arr = np.array([1, 2, 3, 4, 5])
index_arr = np.array([0, 2, 4])
print(arr[index_arr])  # 输出:[1 3 5]
arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
row_indices = np.array([0, 1, 2])
col_indices = np.array([0, 1, 2])
print(arr[row_indices, col_indices]) # 输出:第0行的第0列的元素,以此类推得到:[1 5 9]

6. 修改数组元素

可以使用索引和切片来修改数组中的元素。

arr = np.array([1, 2, 3, 4, 5])
arr[0] = 10
print(arr)  # 输出:[10  2  3  4  5]

arr[1:4] = [20, 30, 40]
print(arr)  # 输出:[10 20 30 40  5]
arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
arr[0, 0] = 10
print(arr)
# 输出:
# [[10  2  3]
#  [ 4  5  6]
#  [ 7  8  9]]

arr[0:2, 1:3] = [[20, 30], [50, 60]]
print(arr)
# 输出:
# [[10 20 30]
#  [ 4 50 60]
#  [ 7  8  9]]

数组组合

1. 拼接

np.concatenate((a1, a2, ...), axis=0, out=None, dtype=None, casting="same_kind")

说明:

  • 用于将多个数组沿指定的轴连接在一起。

参数说明

  • (a1, a2, ...): 要连接的数组序列。这些数组必须具有相同的形状,除了连接轴之外
  • axis: 可选参数,指定连接的轴。默认情况下,axis=0,表示沿着第一个轴连接。
  • out: 可选参数,如果提供,结果将被放入这个数组中。
  • dtype: 可选参数,如果提供,目标数组将具有此类型。
  • casting: 可选参数,控制可以发生的数据转换类型。

注意事项

  • 要连接的数组必须具有相同的维度,除了连接轴之外。
  • 可以使用 axis 参数指定连接的轴。
  • 如果没有提供 axis 参数,则默认沿着第一个轴连接。
  1. 沿着第一个轴连接
   import numpy as np

   arr1 = np.array([[1, 2], [3, 4]])
   arr2 = np.array([[5, 6], [7, 8]])

   concatenated_arr = np.concatenate((arr1, arr2), axis=0)
   print(concatenated_arr)
   # 输出:
   # [[1 2]
   #  [3 4]
   #  [5 6]
   #  [7 8]]
  1. 沿着第二个轴连接

    arr1 = np.array([[1, 2], [3, 4]])
    arr2 = np.array([[5, 6], [7, 8]])
    
    concatenated_arr = np.concatenate((arr1, arr2), axis=1)
    print(concatenated_arr)
    # 输出:
    # [[1 2 5 6]
    #  [3 4 7 8]]
    
  2. 连接一维数组

    arr1 = np.array([1, 2, 3])
    arr2 = np.array([4, 5, 6])
    
    concatenated_arr = np.concatenate((arr1, arr2))
    print(concatenated_arr)  # 输出:[1 2 3 4 5 6]
    
  3. 连接多维数组

arr1 = np.arange(12).reshape((2, 3, 2))
arr2 = np.arange(12, 24).reshape((2, 3, 2))

concatenated_arr = np.concatenate((arr1, arr2), axis=0)# 输出:(4, 3, 2)

# array([[[ 0,  1],
# 	   [ 2,  3],
# 	   [ 4,  5]],

# 	  [[ 6,  7],
# 	   [ 8,  9],
# 	   [10, 11]],

# 	  [[12, 13],
# 	   [14, 15],
# 	   [16, 17]],

# 	  [[18, 19],
# 	   [20, 21],
# 	   [22, 23]]])
np.concatenate((arr1, arr2), axis=1)# 输出:(2, 6, 2) 
#  array([[[ 0,  1],
#         [ 2,  3],
#         [ 4,  5],
#         [12, 13],
#         [14, 15],
#         [16, 17]],

#        [[ 6,  7],
#         [ 8,  9],
#         [10, 11],
#         [18, 19],
#         [20, 21],
#         [22, 23]]])
np.concatenate((arr1, arr2), axis=2)# 输出:(2, 3, 4)
# array([[[ 0,  1, 12, 13],
#         [ 2,  3, 14, 15],
#         [ 4,  5, 16, 17]],

#        [[ 6,  7, 18, 19],
#         [ 8,  9, 20, 21],
#         [10, 11, 22, 23]]])

2. 堆叠

np.stack(arrays, axis=0, out=None)

说明:

  • 用于沿着新的轴堆叠数组序列。它将一系列数组沿着指定的轴堆叠在一起,从而创建一个新的数组。

参数说明

  • arrays: 要堆叠的数组序列。每个数组必须具有相同的形状
  • axis: 可选参数,指定堆叠的轴。默认情况下,axis=0,表示沿着第一个轴堆叠。
  • out: 可选参数,如果提供,结果将被放入这个数组中。
    注意事项
  • 要堆叠的数组必须具有相同的形状。
  • 可以使用 axis 参数指定堆叠的轴。
  • 如果没有提供 axis 参数,则默认沿着第一个轴堆叠。
  • np.stack()在指定的轴上创建一个新的维度
  1. 沿着第一个轴堆叠

    import numpy as np
    
    arr1 = np.array([1, 2, 3])
    arr2 = np.array([4, 5, 6])
    
    stacked_arr = np.stack((arr1, arr2), axis=0)
    print(stacked_arr)
    # 输出:
    # [[1 2 3]
    #  [4 5 6]]
    
  2. 沿着第二个轴堆叠

    arr1 = np.array([1, 2, 3])
    arr2 = np.array([4, 5, 6])
    
    stacked_arr = np.stack((arr1, arr2), axis=1)
    print(stacked_arr)
    # 输出:
    # [[1 4]
    #  [2 5]
    #  [3 6]]
    
  3. 堆叠二维数组

arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])

stacked_arr = np.stack((arr1, arr2), axis=0)  # 按行堆叠到一起 (2, 2, 2)
print(stacked_arr)
# 输出:
# [[[1 2]
#   [3 4]]
#
#  [[5 6]
#   [7 8]]]
  1. 指定堆叠轴

    arr1 = np.array([[1, 2], [3, 4]])
    arr2 = np.array([[5, 6], [7, 8]])
    
    stacked_arr = np.stack((arr1, arr2), axis=1) # 按列堆叠到一起  (2, 2, 2)
    print(stacked_arr)
    # 输出:
    # [[[1 2]
    #   [5 6]]
    #
    #  [[3 4]
    #   [7 8]]]
    
  2. 堆叠多维数组

arr1 = np.arange(12).reshape((2, 3, 2))
arr2 = np.arange(12, 24).reshape((2, 3, 2))

np.stack((arr1, arr2), axis=0)# 输出:(2, 2, 3, 2)
# array([[[[ 0,  1],
         # [ 2,  3],
         # [ 4,  5]],

        # [[ 6,  7],
         # [ 8,  9],
         # [10, 11]]],


       # [[[12, 13],
         # [14, 15],
         # [16, 17]],

        # [[18, 19],
         # [20, 21],
         # [22, 23]]]])

np.stack((arr1, arr2), axis=1) # 输出:(2, 2, 3, 2)
# array([[[[ 0,  1],
         # [ 2,  3],
         # [ 4,  5]],

        # [[12, 13],
         # [14, 15],
         # [16, 17]]],

       # [[[ 6,  7],
         # [ 8,  9],
         # [10, 11]],

        # [[18, 19],
         # [20, 21],
         # [22, 23]]]])
np.stack((arr1, arr2), axis=2)# 输出:(2, 3, 2, 2)
# array([[[[ 0,  1],
         # [12, 13]],

        # [[ 2,  3],
         # [14, 15]],

        # [[ 4,  5],
         # [16, 17]]],


       # [[[ 6,  7],
         # [18, 19]],

        # [[ 8,  9],
         # [20, 21]],

        # [[10, 11],
         # [22, 23]]]])

3. 拼接和堆叠的区别

特性 拼接(Concatenate) 堆叠(Stack)
功能 沿着现有轴连接数组 沿着新轴堆叠数组
维度 不增加维度 增加一个维度
形状要求 除了连接轴外形状相同 形状必须相同
主要函数 np.concatenate() np.stack()

4. 重复

np.repeat(a, repeats, axis=None)

说明

  • np.repeat()用于重复数组中的元素。它可以沿着指定的轴重复元素,或者重复整个数组。
    参数说明
  • a: 输入数组。
  • repeats: 重复的次数。可以是一个整数,表示所有元素重复相同的次数;也可以是一个数组,表示每个元素重复的次数
  • axis: 可选参数,指定沿着哪个轴重复元素。默认情况下,axis=None,表示将数组展平后重复。
    注意事项
  • 如果没有提供 axis 参数,则将数组展平后重复
  • 如果 repeats 是一个数组,则其长度必须与指定轴的长度相同
  • np.repeat() 会返回一个新的数组,原始数组不会被修改
  1. 重复整个数组

    import numpy as np
    arr = np.array([1, 2, 3])
    repeated_arr = np.repeat(arr, 2)
    print(repeated_arr)  # 输出:[1 1 2 2 3 3]
    
  2. 沿着指定的轴重复元素

arr = np.array([[1, 2], [3, 4]])
repeated_arr_axis0 = np.repeat(arr, 2, axis=0)
print(repeated_arr_axis0)
# 输出:
# [[1 2]
#  [1 2]
#  [3 4]
#  [3 4]]

repeated_arr_axis1 = np.repeat(arr, 2, axis=1)
print(repeated_arr_axis1)
# 输出:
# [[1 1 2 2]
#  [3 3 4 4]]
  1. 使用数组指定每个元素的重复次数
arr = np.array([1, 2, 3])
repeats = np.array([3, 2, 1])
repeated_arr = np.repeat(arr, repeats)
print(repeated_arr)  # 输出:[1 1 1 2 2 3]
  1. 重复多维数组
arr = np.array([[1, 2], [3, 4]])
repeats_axis0 = [1, 2]
repeated_arr_axis0 = np.repeat(arr, repeats_axis0, axis=0)
print(repeated_arr_axis0)
# 输出:
# [[1 2]
#  [3 4]
#  [3 4]]

repeats_axis1 = [2, 1]
repeated_arr_axis1 = np.repeat(arr, repeats_axis1, axis=1)
print(repeated_arr_axis1)
# 输出:
# [[1 1 2]
#  [3 3 4]]

三维数组

import numpy as np

# 创建一个三维数组
arr = np.arange(24).reshape((2, 3, 4))
print("原始数组:")
print(arr)
# 输出:
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

# 沿着 axis=0 重复
repeated_arr_axis0 = np.repeat(arr, 2, axis=0)# 输出:(4, 3, 4)

# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
#
#  [[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

# 沿着 axis=1 重复
repeated_arr_axis1 = np.repeat(arr, 2, axis=1)# 输出:(2, 6, 4)

# [[[ 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]
#   [16 17 18 19]
#   [16 17 18 19]
#   [20 21 22 23]
#   [20 21 22 23]]]

# 沿着 axis=2 重复
repeated_arr_axis2 = np.repeat(arr, 2, axis=2) # 输出:(2, 3, 8)

# [[[ 0  0  1  1  2  2  3  3]
#   [ 4  4  5  5  6  6  7  7]
#   [ 8  8  9  9 10 10 11 11]]
#
#  [[12 12 13 13 14 14 15 15]
#   [16 16 17 17 18 18 19 19]
#   [20 20 21 21 22 22 23 23]]]

四维数组


# 创建一个四维数组
arr = np.arange(48).reshape((2, 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]]]
#
#
# [[[24 25 26 27]
#   [28 29 30 31]
#   [32 33 34 35]]
#
#  [[36 37 38 39]
#   [40 41 42 43]
#   [44 45 46 47]]]]

# 沿着 axis=0 重复
repeated_arr_axis0 = np.repeat(arr, 2, axis=0)# 输出:(4, 2, 3, 4)

# 沿着 axis=1 重复
repeated_arr_axis1 = np.repeat(arr, 2, axis=1)# 输出:(2, 4, 3, 4)

# 沿着 axis=2 重复
repeated_arr_axis2 = np.repeat(arr, 2, axis=2)# 输出:(2, 2, 6, 4)

# 沿着 axis=3 重复
repeated_arr_axis3 = np.repeat(arr, 2, axis=3) # 输出:(2, 2, 3, 8)

5. 拆分

np.split(ary, indices_or_sections, axis=0)

说明:

  • 用于将一个数组分割成多个子数组。你可以指定分割的轴和分割的方式。
    参数说明
  • ary: 要分割的数组。
  • indices_or_sections:
    • 整数:表示将数组平均分割成多少个子数组。
    • 数组:表示在哪些位置进行分割。
  • axis: 可选参数,指定沿着哪个轴进行分割。默认情况下,axis=0,表示沿着第一个轴割。
    注意事项
  • 如果 indices_or_sections 是一个整数,则数组必须能够被平均分割。
  • 如果 indices_or_sections 是一个数组,则数组中的元素必须是递增的。
  • np.split() 会返回一个包含子数组的列表。
  1. 平均分割成多个子数组

    import numpy as np
    
    arr = np.array([1, 2, 3, 4, 5, 6])
    sub_arrays = np.split(arr, 3)
    print(sub_arrays)
    # 输出:[array([1, 2]), array([3, 4]), array([5, 6])]
    
  2. 在指定位置进行分割

arr = np.array([1, 2, 3, 4, 5, 6])
sub_arrays = np.split(arr, [2, 4]) # 在索引2和索引4前面进行分割
print(sub_arrays)
# 输出:[array([1, 2]), array([3, 4]), array([5, 6])]
  1. 沿着指定的轴分割二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
np.split(arr, 2, axis=0)

# 输出:[array([[1, 2, 3]]), array([[4, 5, 6]])]

sub_arrays_axis1 = np.split(arr, 3, axis=1)
print(sub_arrays_axis1)
# 输出:[array([[1], [4]]), array([[2], [5]]), array([[3], [6]])]
  1. 分割多维数组
arr = np.arange(24).reshape((2, 3, 4))
# array([[[ 0,  1,  2,  3],
        # [ 4,  5,  6,  7],
        # [ 8,  9, 10, 11]],

       # [[12, 13, 14, 15],
        # [16, 17, 18, 19],
        # [20, 21, 22, 23]]])
sub_arrays_axis0 = np.split(arr, 2, axis=0)
# 输出为两个子数组,但是是同时返回的,也可以采用 a, b = np.split(arr, 2, axis=0)的方式
# [array([[[ 0,  1,  2,  3],
        # [ 4,  5,  6,  7],
        # [ 8,  9, 10, 11]]]), array([[[12, 13, 14, 15],
        # [16, 17, 18, 19],
        # [20, 21, 22, 23]]])]
print(sub_arrays_axis0[0].shape)  # 输出:(1, 3, 4)
print(sub_arrays_axis0[1].shape)  # 输出:(1, 3, 4)

sub_arrays_axis1 = np.split(arr, 3, axis=1)
# [array([[[ 0,  1,  2,  3]],

       # [[12, 13, 14, 15]]]), array([[[ 4,  5,  6,  7]],

       # [[16, 17, 18, 19]]]), array([[[ 8,  9, 10, 11]],

       # [[20, 21, 22, 23]]])]
print(sub_arrays_axis1[0].shape)  # 输出:(2, 1, 4)
print(sub_arrays_axis1[1].shape)  # 输出:(2, 1, 4)
print(sub_arrays_axis1[2].shape)  # 输出:(2, 1, 4)

sub_arrays_axis2 = np.split(arr, 4, axis=2)
# [array([[[ 0],
        # [ 4],
        # [ 8]],

       # [[12],
        # [16],
        # [20]]]), array([[[ 1],
        # [ 5],
        # [ 9]],

       # [[13],
        # [17],
        # [21]]]), array([[[ 2],
        # [ 6],
        # [10]],

       # [[14],
        # [18],
        # [22]]]), array([[[ 3],
        # [ 7],
        # [11]],

       # [[15],
        # [19],
        # [23]]])]
print(sub_arrays_axis2[0].shape)  # 输出:(2, 3, 1)
print(sub_arrays_axis2[1].shape)  # 输出:(2, 3, 1)
print(sub_arrays_axis2[2].shape)  # 输出:(2, 3, 1)
print(sub_arrays_axis2[3].shape)  # 输出:(2, 3, 1)
  1. 指定分割位置
arr = np.arange(10)
sub_arrays = np.split(arr, [3, 7])
print(sub_arrays)
# 输出:[array([0, 1, 2]), array([3, 4, 5, 6]), array([7, 8, 9])]

筛选

从「整体」中统一筛选出「符合条件」的内容

  • 条件筛选:使用布尔索引 arr[condition]
  • 提取(按条件):使用 np.where() 函数。
  • 抽样(按分布):使用 np.random.choice() 函数。
  • 最大最小索引:使用 np.argmax()np.argmin() 函数。
  • 查找特殊值:使用 np.nanargmax()np.nanargmin() 函数。

1. 条件筛选

arr[条件]
  • 示例
    import numpy as np
    
    arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    # 筛选出大于 5 的元素
    filtered_arr = arr[arr > 5]
    print(filtered_arr)  # 输出:[ 6  7  8  9 10]
    # 筛选出偶数
    even_arr = arr[arr % 2 == 0]
    print(even_arr)  # 输出:[ 2  4  6  8 10]
    # 多个条件组合
    combined_arr = arr[(arr > 3) & (arr < 8)]
    print(combined_arr)  # 输出:[4 5 6 7]
    

2. 提取(按条件)

np.where() 函数可以根据条件提取数组中的元素。

a = np.where(condition, x, y) # 如果 condition 为 True,则返回 x,否则返回 y。
b = np.where(condition)      # 返回满足 condition 的元素的索引。
  • 示例
    arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    
    # 根据条件提取元素
    extracted_arr = np.where(arr > 5, arr, 0)
    print(extracted_arr)  # 输出:[0 0 0 0 0 6 7 8 9 10]
    
    # 返回满足条件的索引
    indices = np.where(arr > 5)
    print(indices)  # 输出:(array([5, 6, 7, 8, 9]),)
    

3. 抽样(按分布)

a = np.random.choice(arr, size = None, replace=True, p=None) #函数可以从数组中进行随机抽样。

参数说明

  • arr: 要抽样的数组。
  • size: 抽样的数量。
  • replace: 是否允许重复抽样。
  • p: 每个元素被抽样的概率。

示例

arr = np.array([1, 2, 3, 4, 5])

# 随机抽取 3 个元素,允许重复
sampled_arr = np.random.choice(arr, size=3, replace=True)
print(sampled_arr)  # 输出:例如 [2 5 1]

# 随机抽取 3 个元素,不允许重复
sampled_arr_no_replace = np.random.choice(arr, size=3, replace=False)
print(sampled_arr_no_replace)  # 输出:例如 [3 1 4]

# 按指定概率抽样
probabilities = [0.1, 0.2, 0.3, 0.2, 0.2]
sampled_arr_with_prob = np.random.choice(arr, size=3, replace=True, p=probabilities)
print(sampled_arr_with_prob)  # 输出:例如 [3 2 3]

4. 最大最小索引(特殊值)

a = np.argmax(arr):返回数组中最大值的索引。
b = np.argmin(arr):返回数组中最小值的索引。
  • 示例
    arr = np.array([3, 1, 4, 1, 5, 9, 2, 6])
    
    # 最大值的索引
    max_index = np.argmax(arr)
    print(max_index)  # 输出:5
    
    # 最小值的索引
    min_index = np.argmin(arr)
    print(min_index)  # 输出:1
    

5. 查找特殊值

a = np.nanargmax(arr):#返回数组中最大值的索引,忽略 NaN 值。
b = np.nanargmin(arr):#返回数组中最小值的索引,忽略 NaN 值。
  • 示例
    arr = np.array([3, 1, np.nan, 4, 5, 9, 2, 6])
    
    # 最大值的索引,忽略 NaN 值
    max_index = np.nanargmax(arr)
    print(max_index)  # 输出:5
    
    # 最小值的索引,忽略 NaN 值
    min_index = np.nanargmin(arr)
    print(min_index)  # 输出:1
    

文件读写

1. 写文件

1.1. 保存单个数组

np.save(位置,数组)
  • 功能:以 NumPy 专用的 .npy 格式保存单个数组到文件。
  • 示例
import numpy as np

# 创建一个数组
arr = np.arange(10).reshape((2, 5))

# 保存数组到文件
np.save('my_array.npy', arr)

1.2. 保存多个数组

np.savez(位置,数组)
  • 功能:以 .npz 格式保存多个数组到一个文件中。
  • 示例
    import numpy as np
    
    # 创建多个数组
    arr1 = np.arange(5)
    arr2 = np.arange(5, 10)
    
    # 保存多个数组到文件
    np.savez('multiple_arrays.npz', array1=arr1, array2=arr2)
    

1.3. 保存为文本

np.savetxt(位置,数组索引名和对应名,分割符)
  • 功能:以文本格式保存数组数据到文件。
  • 示例
    import numpy as np
    
    # 创建一个数组
    arr = np.arange(10).reshape((2, 5))
    
    # 保存数组到文本文件
    np.savetxt('my_array.txt', arr, delimiter=',', fmt='%d')
    

1.4. 保存为 CSV

  • 功能:将 NumPy 数组转换为 DataFrame,然后保存到文件(例如 CSV 文件)。
  • 示例
    import numpy as np
    import pandas as pd
    
    # 创建一个数组
    arr = np.arange(10).reshape((2, 5))
    
    # 将数组转换为 DataFrame
    df = pd.DataFrame(arr)
    
    # 保存到 CSV 文件
    df.to_csv('my_array.csv', index=False, header=False)
    

2. 读文件

2.1. 读取文件

 np.load(文件位置文件名)
  • 功能:从 .npy.npz 文件加载数组数据。
    import numpy as np
    
    # 从 .npy 文件加载数组
    loaded_arr = np.load('my_array.npy')
    print(loaded_arr)
    
    # 从 .npz 文件加载多个数组
    loaded_data = np.load('multiple_arrays.npz')
    print(loaded_data['array1'])
    print(loaded_data['array2'])
    

2.2. 读取文本文件中的数组

np.loadtxt(文件名,分割符)
  • 功能:从文本文件加载数组数据。
    import numpy as np
    
    # 从文本文件加载数组
    loaded_arr = np.loadtxt('my_array.txt', delimiter=',', dtype=int)
    print(loaded_arr)
    

2.3. 从 CSV 中加载

  • 功能:从文件(例如 CSV 文件)加载数据到 DataFrame,然后转换为 NumPy 数组。
    import numpy as np
    import pandas as pd
    
    # 从 CSV 文件加载数据
    loaded_df = pd.read_csv('my_array.csv', header=None)
    loaded_arr = loaded_df.values
    print(loaded_arr)
    
posted @ 2025-03-15 23:22  弈北川  阅读(68)  评论(0)    收藏  举报