1、NumPy基础

1.1.安装和导入NumPy

1. 安装NumPy

  • 在终端或命令行中运行以下命令:

    pip install numpy
    

    在终端或命令行中安装NumPy之前需要先安装Python。NumPy是Python的一个扩展库,依赖于Python环境,因此没有Python的话无法安装和使用NumPy。

  • 如果你已经安装了Anaconda,可以用它来安装:

    conda install numpy
    

    conda 是 Anaconda 提供的包管理和环境管理工具。它能够安装、更新、卸载各种包(如 NumPy、Pandas 等)并管理不同的 Python 环境,让开发者更容易切换和管理不同项目所需的依赖库。conda 不仅支持 Python 包,还可以管理其他语言的包,因此比 pip 更强大。

2. 导入NumPy

安装完成后,在Python代码中导入NumPy通常使用import numpy as np,这使得后续使用NumPy时可以简化代码。

示例如下:

import numpy as np

现在,你可以使用 np 来调用NumPy的函数和属性了。

1.2.数组的基本概念(ndarray)

ndarray(N-dimensional array)是NumPy中用于表示多维数组的核心数据结构。它可以存储多维数据,例如一维数组、二维矩阵,甚至更高维度的数据。这使得 ndarray 非常适合处理数值计算、数据分析、机器学习等场景。下面是一些 ndarray 的基本概念和特点:

1. ndarray 的基本结构

ndarray 是一个多维、同质(即数组中所有元素类型相同)的数据容器。它由以下几部分组成:

  • 数据类型 (dtype):指定数组中元素的类型,如整数 (int)、浮点数 (float)、布尔值等。
  • 形状 (shape):数组的维度信息。shape 属性表示每一维度的大小。
  • 维度 (ndim):数组的维数,表示该数组是几维的。
  • 大小 (size):数组中元素的总数量。

2. 创建 ndarray

可以使用 np.array() 方法将Python的列表或元组转换为 ndarray。例如:

import numpy as np

# 创建一维数组
arr1 = np.array([1, 2, 3, 4])
print(arr1)  # 输出:[1 2 3 4]

# 创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2)  
# 输出:
# [[1 2 3]
#  [4 5 6]]

3.ndarray 的基本属性

每个 ndarray 对象都具有一些常用的属性,可以帮助我们了解数组的结构:

# 示例数组
arr = np.array([[1, 2, 3], [4, 5, 6]])

# 数组的形状(shape)
print(arr.shape)  # 输出:(2, 3)

# 数组的维度(ndim)
print(arr.ndim)   # 输出:2

# 数组的大小(size)
print(arr.size)   # 输出:6

# 数组的数据类型(dtype)
print(arr.dtype)  # 输出:int64(或其他整数类型,取决于系统)

4. 多维数组

NumPy支持任意维度的数组,可以是1维、2维、3维,甚至更高维度。如下所示:

# 三维数组
arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(arr3)
# 输出:
# [[[1 2]
#   [3 4]]
#
#  [[5 6]
#   [7 8]]]

5. ndarray 的特点

  • 快速高效ndarray 是基于C语言实现的,执行速度很快。
  • 广播机制:支持在不同形状的数组之间执行运算。
  • 支持多种运算:可以在数组上执行算术运算、逻辑运算、索引、切片等各种操作。

ndarray 是NumPy中最核心的对象,理解它有助于深入学习数值计算和数据处理。

1.3.数组基础

1.3.1.数据类型

1.整数型数组与浮点型数组

为了克服列表的缺点,一个NumPy数组只容纳一种数据类型,以节约内存。以整数型数组与浮点型数组为例:

import numpy as np 

# 创建整数型数组 
arr1 = np.array([1, 2, 3])		#元素若都是整型,则为整数型数组
print(arr1)  # 输出: [1 2 3] 

# 创建浮点型数组 
arr2 = np.array([1.0, 2, 3]) 	#内含浮点数,则为浮点型数组
print(arr2)  # 输出: [1. 2. 3.] 

注意,使用 print 输出 NumPy 数组后,元素之间没有逗号,这有两个好处是可以可将之与 Python 列表区分开来,二是避免逗号与小数点之间的混淆。

2.同化定理

一个人的力量是无法改变全体的,在实际操作中要注意:

  • 往整数型数组里插入浮点数,该浮点数会自动被截断为整数;
  • 往浮点型数组里插入整数,该整数会自动升级为浮点数;
import numpy as np

# 创建整数型数组
arr1 = np.array([1, 2, 3])
arr1[0] = 100.9  # 插入浮点数,被截断,数组仍为整数型
print(arr1)  # 输出: [100   2   3]


# 创建浮点型数组
arr2 = np.array([1.0, 2, 3])
arr2[1] = 10  # 插入整数型,被升级,数组仍为浮点型
print(arr2)  # 输出: [1. 10. 3.]

3.共同改变定理

同化定理告诉我们,整数型数组和浮点型数组之间的界限十分严格,那么如何将这两种数据类型的数组进行相互转化呢?既然某一个人容易被集体所同化那只要全体共同改变,自然就可以成功

整数型数组和浮点型数组相互转换,规范的方法是使用.astype()方法。

import numpy as np

# 创建整数型数组
arr1 = np.array([1, 2, 3])
print(arr1)  # 输出: [1 2 3]

# 将整数型数组转换为浮点型数组
arr2 = arr1.astype(float)
print(arr2)  # 输出: [1. 2. 3.]

# 将浮点型数组转换回整数型数组
arr3 = arr2.astype(int)
print(arr3)  # 输出: [1 2 3]

除了上述方法,只要满足共同改变定理,整数型数组和浮点型数组仍然可以互相转换。最常见的是整数型数组在运算过程中升级为浮点型数组,示例如下:

import numpy as np

# 整数型数组
arr = np.array([1, 2, 3])
print(arr)  # 输出: [1 2 3]

# 整数型数组与浮点数做运算
print(arr + 0.0)  # 输出: [1. 2. 3.]
print(arr * 1.0)  # 输出: [1. 2. 3.]

# 整数型数组遇到除法(即便是除以整数)
print(arr / 1)  # 输出: [1. 2. 3.]

# 整数型数组与浮点型数组做运算
int_arr = np.array([1, 2, 3])
float_arr = np.array([1.0, 2, 3])
print(int_arr + float_arr)  # 输出: [2. 4. 6.]

整数型数组很好升级,但浮点型数组在运算过程中一般不会降级。

1.3.2.数组维度

在深度学习中,三维及其以上的数组出现较少,因此主要讲解一维数组和二维数组。学习了一维和二维数组后,可以很容易地类推到三维数组。

  • 不同维度数组的表示,从外观上的本质区别是

    • 一维数组使用1层中括号表示。

    • 二维数组使用2层中括号表示。

    • 三维数组使用3层中括号表示。

  • 数组形状参数

    • 一维数组的形状参数形如:x(x,)
    • 二维数组的形状参数形如:(x, y)
    • 三维数组的形状参数形如:(x, y, z)
      • 第一个维度(深度)有x个元素,
      • 第二个维度(行)有y个元素,
      • 第三个维度(列)有z个元素。
  • 数组形状示例

    • 当数组有1层中括号,如[1, 2, 3],则其为一维数组,其形状是3(3,)

    • 当数组有2层中括号,如[[1, 2, 3]],则其为二维数组,其形状是(1, 3)

    • 当数组有3层中括号,如[[[1, 2, 3]]],则其为三维数组,其形状是(1, 1, 3)

这里用后面要讲的 np.ones( ) 函数进行演示,只因其刚好需要传入形状参数。

import numpy as np

#创建一维数组:
arr1 = np.ones(3)
print(arr1)#输出:[1. 1. 1.]

#创建二维数组
arr2 = np.ones((1, 3))
print(arr2)#输出:[[1. 1. 1.]]

#创建三维数组:
arr3 = np.ones((1, 1, 3))
print(arr3)#输出:[[[1. 1. 1.]]]

查看数组的形状:

print(arr1.shape)
print(arr2.shape)
print(arr3.shape)
#输出:
(3,)
(1, 3)
(1, 1, 3)

2、数组的创建

在NumPy中,可以使用多种方法创建数组。以下是一些常用的方法:

2.1. array()

array() 是最常用的创建数组的方法,可以将列表、元组等序列数据转换为 ndarray 数组。

import numpy as np

# 通过列表创建一维数组
arr1 = np.array([1, 2, 3, 4])
print(arr1)  # 输出:[1 2 3 4]

# 通过嵌套列表创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2)
# 输出:
# [[1 2 3]
#  [4 5 6]]

2.2. arange()

arange() 用于生成具有固定步长的等差数组,类似于 Python 的 range() 函数。

import numpy as np

# 创建一个从 0 到 9 的一维数组
arr = np.arange(10)
print(arr)  # 输出:[0 1 2 3 4 5 6 7 8 9]

# 指定起始值、结束值和步长
arr_step = np.arange(2, 10, 2)
print(arr_step)  # 输出:[2 4 6 8]

2.3. linspace()

linspace() 用于创建在指定范围内具有固定数量元素的等间隔数组,常用于生成连续的数据点。

import numpy as np

# 创建一个从 0 到 1 的数组,包含 5 个等间距的值
arr = np.linspace(0, 1, 5)
print(arr)  # 输出:[0.   0.25 0.5  0.75 1. ]

# 创建一个从 0 到 10 的数组,包含 4 个等间距的值
arr_large = np.linspace(0, 10, 4)
print(arr_large)  # 输出:[ 0.  3.33333333  6.66666667 10. ]

2.4. zeros()

zeros() 用于创建所有元素均为 0 的数组,适用于初始化需要全部为 0 的数组。

import numpy as np

# 创建一个一维零数组,长度为 5
arr = np.zeros(5)
print(arr)  # 输出:[0. 0. 0. 0. 0.]

# 创建一个 2x3 的零矩阵
arr_2d = np.zeros((2, 3))
print(arr_2d)
# 输出:
# [[0. 0. 0.]
#  [0. 0. 0.]]

2.5. ones()

ones() 用于创建所有元素均为 1 的数组,适合用于初始化需要全部为 1 的数组。

import numpy as np

# 创建一个一维数组,长度为 5,值全为 1
arr = np.ones(5)
print(arr)  # 输出:[1. 1. 1. 1. 1.]

# 创建一个 2x3 的矩阵,值全为 1
arr_2d = np.ones((2, 3))
print(arr_2d)
# 输出:
# [[1. 1. 1.]
#  [1. 1. 1.]]

2.6. eye()

eye() 创建一个单位矩阵,对角线元素为 1,其他元素为 0。

import numpy as np

# 创建一个 3x3 的单位矩阵
arr = np.eye(3)
print(arr)
# 输出:
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

2.7. random 模块

NumPy 的 random 模块提供了随机数生成的功能,可以生成各种随机数组。

  • np.random.rand()
    生成0到1之间的均匀分布的浮点数,支持指定形状。

    import numpy as np
    
    # 生成一个随机浮点数数组,长度为5
    arr = np.random.rand(5)
    print(arr)  # 输出类似:[0.26674455 0.85674365 0.83504875 0.0947853  0.59059363]
    
    # 生成一个2x3的随机数组
    arr_2d = np.random.rand(2, 3)
    print(arr_2d)
    #输出:[[0.53906339 0.94653916 0.48469193]
    # [0.72947324 0.55864621 0.23548281]]
    
    
  • np.random.randint()
    生成给定范围内的随机整数,支持指定形状。

    # 生成1到10之间的一个随机整数
    rand_int = np.random.randint(1, 10)
    print(rand_int)#输出:9
    
    # 生成1到10之间的2x3的随机整数数组
    arr = np.random.randint(1, 10, size=(2, 3))
    print(arr)
    #输出:[[9 8 2]
    # [9 8 5]]
    
  • np.random.randn()

    生成标准正态分布(均值为0,标准差为1)的随机数,类似于 rand() 但符合正态分布。

    # 生成一个长度为5的正态分布数组
    arr = np.random.randn(5)
    print(arr)#输出:[-0.14451857  0.46234321  0.75082202 -0.66510259  0.52073312]
    
    # 生成一个2x3的正态分布数组
    arr_2d = np.random.randn(2, 3)
    print(arr_2d)
    #输出:[[ 0.94489443 -0.36822856  1.80855408]
    # [ 0.88469963 -0.35445813 -0.73938533]]
    
    
  • np.random.choice()

    从给定的一维数组中随机抽取元素,允许指定抽取的数量以及是否放回(即可以重复抽取)。

    # 从数组 [1, 2, 3, 4, 5] 中随机抽取一个元素
    rand_choice = np.random.choice([1, 2, 3, 4, 5])
    print(rand_choice)#输出:4
    
    # 随机抽取3个元素,允许重复
    arr_choice = np.random.choice([1, 2, 3, 4, 5], size=3, replace=True)
    print(arr_choice)#输出:[1 3 3]
    
    # 随机抽取3个元素,不允许重复
    arr_choice_no_replace = np.random.choice([1, 2, 3, 4, 5], size=3, replace=False)
    print(arr_choice_no_replace)#输出:[4 2 1]
    
  • np.random.shuffle()

    在原数组上进行随机排列,改变数组的顺序(原地操作)。

    arr = np.array([1, 2, 3, 4, 5])
    np.random.shuffle(arr)
    print(arr)  # 输出顺序随机排列后的数组:[5 1 2 4 3]
    
  • np.random.permutation()

    生成一个新的随机排列的数组,不改变原数组。

    arr = np.array([1, 2, 3, 4, 5])
    perm = np.random.permutation(arr)
    print(perm)  # 输出一个随机排列的数组:[5 4 1 2 3]
    print(arr)   # 原数组不变:[1 2 3 4 5]
    
  • np.random.uniform()

    生成均匀分布的随机数,可以指定区间范围。

    # 生成一个在1到10之间的均匀分布的随机数
    rand_uniform = np.random.uniform(1, 10)
    print(rand_uniform)#4.6469286168848845
    
    # 生成一个2x3的均匀分布随机数组,区间为1到10
    arr = np.random.uniform(1, 10, size=(2, 3))
    print(arr)
    #[[5.77040181 3.02357949 1.92100856]
    # [4.72454165 8.63431945 5.43633303]]
    
    
  • np.random.normal()

    生成正态分布的随机数,允许设置均值和标准差。

    # 生成一个均值为0,标准差为1的正态分布随机数
    rand_normal = np.random.normal(0, 1)
    print(rand_normal)#1.180951257198756
    
    # 生成一个2x3的正态分布数组,均值为5,标准差为2
    arr = np.random.normal(5, 2, size=(2, 3))
    print(arr)
    #[[5.75662905 5.43292871 8.15551217]
    # [6.76630693 4.04360497 6.49182055]]
    

3、数组的属性

在 NumPy 中,数组的属性用于描述数组的结构和数据特征。以下是对这些属性的详细说明:

3.1. shape:数组的形状

  • shape 是一个元组,表示数组在每个维度上的大小。它描述了数组的形状或布局。
  • 对于二维数组,shape 会返回 (行数, 列数);对于三维数组,返回 (深度, 行数, 列数),依此类推。

示例:

import numpy as np

# 创建一个2x3的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])

# 查看数组的形状
print(arr.shape)  # 输出:(2, 3),表示2行3列

可以通过修改 shape 属性来更改数组的形状:

# 将 2x3 的数组重塑为 3x2
arr.shape = (3, 2)
print(arr)

# 输出:
# [[1 2]
#  [3 4]
#  [5 6]]

3.2. ndim:数组的维度数

  • ndim 是一个整数,表示数组的维度数,即数组的“阶数”。
  • ndim=1 表示一维数组,ndim=2 表示二维数组,以此类推。

示例:

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.ndim)  # 输出:2,表示这是一个二维数组

3.3. size:数组中元素的总数

  • size 是一个整数,表示数组中所有元素的总数。
  • 这个值等于 shape 中所有维度大小的乘积。

示例:

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.size)  # 输出:6,表示数组中总共有6个元素

3.4. dtype:数组的数据类型

  • dtype 表示数组中元素的数据类型,例如 int32float64 等。
  • 数据类型可以在创建数组时指定,也可以在需要时使用 astype() 进行转换。

示例:

# 创建一个浮点数数组
arr_float = np.array([1.0, 2.0, 3.0])

# 查看数组的数据类型
print(arr_float.dtype)  # 输出:float64

可以在创建数组时指定数据类型,或使用 astype() 方法更改数组的数据类型:

# 创建整数类型数组
arr_int = np.array([1, 2, 3], dtype=np.int32)
print(arr_int.dtype)  # 输出:int32

# 转换为浮点数类型
arr_float = arr_int.astype(np.float64)
print(arr_float.dtype)  # 输出:float64

4、数组的基本运算

4.1.算数运算

在 NumPy 中,算术运算可以直接在数组上逐元素进行。除了 Python 的算术运算符(如 +- 等),NumPy 还提供了相应的函数(如 np.add()np.subtract() 等),便于执行逐元素计算。

import numpy as np

# 创建两个数组
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
  • 加法:+np.add()
    逐元素相加,结果为每个对应元素的和。

    # 使用运算符
     # 使用运算符
    result_add = a + b
    print(result_add)  # 输出:[ 6  8 10 12]
    
    # 使用 np.add()
    result_add_func = np.add(a, b)
    print(result_add_func)  # 输出:[ 6  8 10 12]
    
  • 减法:-np.subtract()
    逐元素相减,结果为每个对应元素的差。

    # 使用运算符
    result_multiply = a - b
    print(result_multiply)  # 输出:[-4 -4 -4 -4]
    
    # 使用 np.subtract()
    result_multiply_func = np.subtract(a, b)
    print(result_multiply_func)  # 输出::[-4 -4 -4 -4]
    
  • 乘法:*np.multiply()
    逐元素相乘,结果为每个对应元素的乘积。

    # 使用运算符
    result_multiply = a * b
    print(result_multiply)  # 输出:[ 5 12 21 32]
    
    # 使用 np.multiply()
    result_multiply_func = np.multiply(a, b)
    print(result_multiply_func)  # 输出:[ 5 12 21 32]
    
  • 除法:/np.divide()
    逐元素相除,结果为每个对应元素的商。

    # 使用运算符
    result_divide = a / b
    print(result_divide)  # 输出:[0.2        0.33333333 0.42857143 0.5       ]
    
    # 使用 np.divide()
    result_divide_func = np.divide(a, b)
    print(result_divide_func)  # 输出:[0.2        0.33333333 0.42857143 0.5       ]
    
  • 指数运算:**np.power()
    逐元素计算幂次方。

    # 使用运算符
    result_power = a ** 2
    print(result_power)  # 输出:[ 1  4  9 16]
    
    # 使用 np.power()
    result_power_func = np.power(a, 2)
    print(result_power_func)  # 输出:[ 1  4  9 16]
    
  • 取模:%np.mod()
    逐元素取余数。

    # 使用运算符
    result_mod = a % b
    print(result_mod)  # 输出:[1 2 3 4]
    
    # 使用 np.mod()
    result_mod_func = np.mod(a, b)
    print(result_mod_func)  # 输出:[1 2 3 4]
    
  • 整除://np.floor_divide()
    逐元素整除。

    # 使用运算符
    result_floor_divide = b // a
    print(result_floor_divide)  # 输出:[5 3 2 2]
    
    # 使用 np.floor_divide()
    result_floor_divide_func = np.floor_divide(b, a)
    print(result_floor_divide_func)  # 输出:[5 3 2 2]
    

总结

运算 运算符 函数 示例
加法 + np.add() a + b
减法 - np.subtract() a - b
乘法 * np.multiply() a * b
除法 / np.divide() a / b
指数运算 ** np.power() a ** 2
取模 % np.mod() a % b
整除 // np.floor_divide() b // a

4.2.数组与标量的运算

在 NumPy 中,数组可以与标量进行加、减、乘、除等算术运算。此类运算会自动应用到数组的每个元素上,即逐元素进行操作。这样可以快速对整个数组进行批量计算,而无需写循环。

import numpy as np

# 创建一个数组
arr = np.array([1, 2, 3, 4])

# 每个元素加 10
result_add = arr + 10
print("加法结果:", result_add)  # 输出:[11 12 13 14]

# 每个元素减 2
result_subtract = arr - 2
print("减法结果:", result_subtract)  # 输出:[-1  0  1  2]

# 每个元素乘 3
result_multiply = arr * 3
print("乘法结果:", result_multiply)  # 输出:[ 3  6  9 12]

# 每个元素除以 2
result_divide = arr / 2
print("除法结果:", result_divide)  # 输出:[0.5 1.  1.5 2. ]

# 每个元素求平方
result_power = arr ** 2
print("平方结果:", result_power)  # 输出:[ 1  4  9 16]

#每个元素求余
result_mod = arr%2
print("求余数结果:"result_mod) # 输出;[1 0 1 0]

#每个元素整除
result_floor_divide = arr//2
print("求整除结果:"result_floor_divide) # 输出;[0 1 1 2]

说明:

  • 数组与标量的运算在数组的每个元素上逐个进行,称为逐元素运算
  • NumPy 利用广播机制处理数组和标量的运算,使标量在内部扩展为与数组形状一致,从而完成计算。
  • 数组与标量的运算也可以通过函数进行计算,函数的使用同算数运算一致。

注意事项:

  1. 类型转换:运算结果的数据类型会根据数组和标量的数据类型自动调整。例如,如果数组是整数类型但与浮点数标量运算,结果会转成浮点数。

  2. 兼容性:数组与标量的运算可以适用于任何形状的数组(如一维、二维、三维等)。

4.3.比较运算

1、使用比较符号进行比较

在 NumPy 中,数组可以与标量或另一个数组进行比较运算,这些比较运算逐元素执行,并返回布尔值的数组,表示每个元素的比较结果。

import numpy as np

# 定义两个数组
a = np.array([1, 2, 3, 4])
b = np.array([2, 2, 4, 3])
  • 等于 ==

    #逐元素比较两个数组,返回每个位置是否相等。
    result_eq1 = a == b
    print("等于 (==):", result_eq1)  # 输出:[False  True False False]
    
    #逐元素比较数组中的元素是否等于标量。
    result_eq2 = a == 3
    print("等于 (==):", result_eq2)  # 输出:[False False True False]
    
  • 不等于 !=

    #逐元素比较两个数组,返回每个位置是否不相等。
    result_neq1 = a != b
    print("不等于 (!=):", result_neq1)  # 输出:[ True False  True  True]
    
    #逐元素比较数组中的元素是否不等于标量。
    result_neq2 = a != 3
    print("不等于 (!=):", result_neq2)  # 输出:[ True  True  False  True]
    
  • 大于 >

    #逐元素比较第一个数组是否大于第二个数组的对应元素。
    result_gt1 = a > b
    print("大于 (>):", result_gt1)  # 输出:[False False False  True]
    
    #逐元素比较数组中的元素是否大于标量。
    result_gt2 = a > 3
    print("大于 (>):", result_gt2)  # 输出:[False False False  True]
    
  • 小于 <

    #逐元素比较第一个数组是否小于第二个数组的对应元素。
    result_lt1 = a < b
    print("小于 (<):", result_lt1)  # 输出:[ True False  True False]
    
    #逐元素比较数组中的元素是否小于标量。
    result_lt2 = a < 3
    print("小于 (<):", result_lt2)  # 输出:[ True True  False False]
    
  • 大于等于 >=

    #逐元素比较第一个数组是否大于等于第二个数组的对应元素。
    result_ge1 = a >= b
    print("大于等于 (>=):", result_ge1)  # 输出:[False  True False  True]
    
    #逐元素比较数组中的元素是否大于等于标量。
    result_ge2 = a >= 3
    print("大于等于 (>=):", result_ge2)  # 输出:[False  False True  True]
    
  • 小于等于 <=

    #逐元素比较第一个数组是否小于等于第二个数组的对应元素。
    result_le1 = a <= b
    print("小于等于 (<=):", result_le1)  # 输出:[ True  True  True False]
    
    #逐元素比较数组中的元素是否小于等于标量。
    result_le2 = a <= 3
    print("小于等于 (<=):", result_le2)  # 输出:[ True  True  True False]
    

2、使用函数进行比较

在 NumPy 中,除了使用 ==!=><>=<= 直接进行比较运算外,还可以使用对应的函数来进行逐元素比较。以下是每种比较运算的函数:

  • 比较运算的函数

    运算符 函数 说明
    == np.equal() 检查是否相等
    != np.not_equal() 检查是否不相等
    > np.greater() 检查是否大于
    < np.less() 检查是否小于
    >= np.greater_equal() 检查是否大于等于
    <= np.less_equal() 检查是否小于等于
  • 示例代码

    import numpy as np
    
    # 定义两个数组
    a = np.array([1, 2, 3, 4])
    b = np.array([2, 2, 3, 1])
    
    # 使用比较函数
    print("等于 (np.equal):", np.equal(a, b))           # 输出:[False  True  True False]
    print("不等于 (np.not_equal):", np.not_equal(a, b)) # 输出:[ True False False  True]
    print("大于 (np.greater):", np.greater(a, b))       # 输出:[False False False  True]
    print("小于 (np.less):", np.less(a, b))             # 输出:[ True False False False]
    print("大于等于 (np.greater_equal):", np.greater_equal(a, b))  # 输出:[False  True  True  True]
    print("小于等于 (np.less_equal):", np.less_equal(a, b))        # 输出:[ True  True  True False]
    
  • 说明

    • 这些函数适用于数组与数组之间的比较,或者数组与标量之间的比较。

    • 返回值是一个布尔数组,表示每个位置的比较结果。

4.4.逻辑运算

1、在布尔数组上使用逻辑运算符

在 NumPy 中,逻辑运算符 &|~^ 可用于对布尔数组进行逐元素的逻辑操作。以下是每种逻辑运算的详细说明和示例:

import numpy as np

# 创建两个布尔数组
a = np.array([True, False, True, False])
b = np.array([True, True, False, False])
  • 逻辑与 (&np.logical_and())
    逐元素执行逻辑与操作,仅当两个数组的对应元素都为 True 时返回 True,否则返回 False

    result_and = a & b
    print("逻辑与 (&):", result_and)  # 输出:[ True False False False]
    
  • 逻辑或(|np.logical_or())
    逐元素执行逻辑或操作,只要两个数组的对应元素中有一个为 True 就返回 True,否则返回 False

    result_or = a | b
    print("逻辑或 (|):", result_or)  # 输出:[ True  True  True False]
    
  • 逻辑非( ~np.logical_not())
    逐元素对数组进行逻辑非操作,即将 True 转为 False,将 False 转为 True

     result_not = ~a
    print("逻辑非 (~):", result_not)  # 输出:[False  True False  True]
    
  • 逻辑异或 (^np.logical_xor())

    逐元素执行逻辑异或操作,仅当两个数组的对应元素一个为 True 且另一个为 False 时返回 True,否则返回 False

    result_xor = a ^ b
    print("逻辑异或 (^):", result_xor)  # 输出:[False  True  True False]
    

2、NumPy 的逻辑运算函数

NumPy 也提供了函数形式的逻辑运算,这些函数可以处理不同数据类型的数组,并且可以指定输出的数据类型。下面是如何使用这些函数的例子:

  1. np.logical_and(a, b):执行逻辑与操作。
  2. np.logical_or(a, b):执行逻辑或操作。
  3. np.logical_not(a):执行逻辑非操作。
  4. np.logical_xor(a, b):执行逻辑异或操作。

这些函数可以接受一个额外的参数 dtype,用于指定输出数组的数据类型。如果没有指定 dtype,则输出数组的数据类型将自动决定,以能够表示操作结果。

  • 示例代码

    import numpy as np
    
    a = np.array([True, False, True, True])
    b = np.array([True, True, False, False])
    
    # 逻辑与操作
    result_and = np.logical_and(a, b)
    print("Logical AND:", result_and)
    
    # 逻辑或操作
    result_or = np.logical_or(a, b)
    print("Logical OR:", result_or)
    
    # 逻辑非操作
    result_not = np.logical_not(a)
    print("Logical NOT:", result_not)
    
    # 逻辑异或操作
    result_xor = np.logical_xor(a, b)
    print("Logical XOR:", result_xor)
    
    # 指定输出类型为 int8
    result_and_int8 = np.logical_and(a, b, dtype=np.int8)
    print("Logical AND with int8:", result_and_int8)
    
  • 输出结果:

    Logical AND: [ True False False  True]
    Logical OR: [ True  True  True  True]
    Logical NOT: [False  True False False]
    Logical XOR: [False  True  True False]
    Logical AND with int8: [1 0 0 1]
    

请注意,np.logical_andnp.logical_or 函数要求输入数组中的元素是布尔类型。如果数组包含非布尔类型的元素,你需要先将它们转换为布尔类型,或者使用按位逻辑运算符(&, |, ^)来执行操作。

3、在整数数组上使用逻辑运算符的操作

NumPy 的逻辑运算符 &|~^ 可以用于整数型数组。不过,它们在整数数组上表现为逐元素的位运算,而不是逻辑运算:

示例代码

import numpy as np

# 定义两个整数数组
a = np.array([1, 2, 3, 4])   # 二进制表示为 [0001, 0010, 0011, 0100]
b = np.array([4, 5, 6, 7])   # 二进制表示为 [0100, 0101, 0110, 0111]
  • 逐位与 &

    result_and = a & b
    print("逐位与 (&):", result_and)  # 输出:[0, 0, 2, 4]
    
  • 逐位或 |

    result_or = a | b
    print("逐位或 (|):", result_or)  # 输出:[5, 7, 7, 7]
    
  • 逐位非 ~

    result_not = ~a
    print("逐位非 (~):", result_not)  # 输出:[-2, -3, -4, -5]
    
  • 逐位异或 ^

    result_xor = a ^ b
    print("逐位异或 (^):", result_xor)  # 输出:[5, 7, 5, 3]
    

注意事项

  • 若要在布尔值意义上使用逻辑运算,可以将整数数组与逻辑条件结合使用,例如 (a > 2) & (b < 6),这样条件语句会返回布尔数组,再对其进行逻辑运算。

4.5.矩阵运算

在 NumPy 中,矩阵运算支持多种操作,包括矩阵乘法、转置、逆矩阵、行列式和特征值等。这些操作适用于线性代数计算和科学计算。以下是一些常用的矩阵运算方法:

  • 矩阵乘法

    矩阵乘法不同于逐元素乘法,可以通过 @ 运算符或 np.dot() 函数实现。

    import numpy as np
    
    # 定义两个矩阵
    A = np.array([[1, 2], [3, 4]])
    B = np.array([[5, 6], [7, 8]])
    
    # 使用 @ 进行矩阵乘法
    result_matmul = A @ B
    print("矩阵乘法 (A @ B):\n", result_matmul)
    #输出:
    #矩阵乘法 (A @ B):
    # [[19 22]
    # [43 50]]
    
    # 使用 np.dot() 进行矩阵乘法
    result_dot = np.dot(A, B)
    print("矩阵乘法 (np.dot(A, B)):\n", result_dot)
    #输出:
    #矩阵乘法 np.dot(A, B):
    # [[19 22]
    # [43 50]]
    
  • 矩阵转置

    矩阵转置可以使用 .T 属性或 np.transpose() 函数。

    # 矩阵 A 的转置
    A_T = A.T
    print("矩阵转置 (A.T):\n", A_T)
    #输出:
    #矩阵转置 (A.T):
    # [[1 3]
    # [2 4]]
    
    # 使用 np.transpose()
    A_T_func = np.transpose(A)
    print("矩阵转置 (np.transpose(A)):\n", A_T_func)
    #输出:
    #矩阵转置 np.transpose(A):
    # [[1 3]
    # [2 4]]
    
  • 逆矩阵

    矩阵的逆可以使用 np.linalg.inv() 函数,前提是矩阵必须是方阵,且行列式不为零。

    # 计算 A 的逆矩阵
    A_inv = np.linalg.inv(A)
    print("逆矩阵 (np.linalg.inv(A)):\n", A_inv)
    #输出:
    #逆矩阵 (np.linalg.inv(A)):
    # [[-2.   1. ]
    # [ 1.5 -0.5]]
    
  • 行列式

    行列式可以用 np.linalg.det() 函数计算。

    # 计算 A 的行列式
    det_A = np.linalg.det(A)
    print("行列式 (np.linalg.det(A)):", det_A)
    #输出:行列式 (np.linalg.det(A)): -2.0
    
  • 特征值和特征向量

    可以使用 np.linalg.eig() 函数来计算方阵的特征值和特征向量。

    调用 np.linalg.eig() 将返回两个数组:一个包含特征值,另一个包含对应的特征向量。

    np.linalg.eigvals() 是 NumPy 中用于计算矩阵特征值的函数,但不同于 np.linalg.eig(),它只返回特征值,而不返回对应的特征向量。

    # 计算 A 的特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(A)
    print("特征值:", eigenvalues)
    print("特征向量:\n", eigenvectors)
    #输出:
    #特征值: [-0.37228132  5.37228132]
    #特征向量:
    # [[-0.82456484 -0.41597356]
    # [ 0.56576746 -0.90937671]]
    
  • 矩阵的范数

    使用 np.linalg.norm() 计算矩阵的范数。

    # 计算矩阵 A 的范数
    norm_A = np.linalg.norm(A)
    print("矩阵的范数 (np.linalg.norm(A)):", norm_A)
    #矩阵的范数 (np.linalg.norm(A)): 5.477225575051661
    
  • 点积(逐元素乘积)

    可以用 * 进行逐元素乘法(Hadamard 乘积),不等同于矩阵乘法。

    # 逐元素乘积
    elementwise_product = A * B
    print("逐元素乘积 (A * B):\n", elementwise_product)
    #输出:
    #逐元素乘积 (A * B):
    # [[ 5 12]
    # [21 32]]
    

在 NumPy 中,聚合运算用于对数组中的元素进行汇总计算,例如求和、求平均值、求最大值和最小值等。这些操作非常高效,广泛用于数据分析和统计。

4.6.聚合运算

操作 函数 说明
求和 np.sum() 计算数组所有元素的和
求平均值 np.mean() 计算数组所有元素的平均值
求最大值 np.max() 返回数组的最大值
求最小值 np.min() 返回数组的最小值
求乘积 np.prod() 计算数组所有元素的乘积
标准差 np.std() 计算数组所有元素的标准差
方差 np.var() 计算数组所有元素的方差
中位数 np.median() 计算数组的中位数
累积和 np.cumsum() 返回数组的累积和
累积积 np.cumprod() 返回数组的累积积
最大值索引 np.argmax() 返回数组中最大值的索引
最小值索引 np.argmin() 返回数组中最小值的索引

1、一维数组的聚合运算

import numpy as np

# 定义一个数组
a = np.array([1, 2, 3, 4, 5])

#求和 np.sum()
print("求和:", np.sum(a))  # 输出:15

#求平均值 np.mean()
print("平均值:", np.mean(a))  # 输出:3.0

#求最大值 np.max()
print("最大值:", np.max(a))  # 输出:5

# 求最小值 np.min()
print("最小值:", np.min(a))  # 输出:1

#求乘积 np.prod()
print("乘积:", np.prod(a))  # 输出:120

#标准差 np.std()
print("标准差:", np.std(a))  # 输出:1.4142135623730951

#方差 np.var()
print("方差:", np.var(a))  # 输出:2.0


#中位数 np.median()
print("中位数:", np.median(a))  # 输出:3.0


#累积和 np.cumsum()
print("累积和:", np.cumsum(a))  # 输出:[ 1  3  6 10 15]


#累积积 np.cumprod()
print("累积积:", np.cumprod(a))  # 输出:[  1   2   6  24 120]


#最大值索引 np.argmax()
print("最大值索引:", np.argmax(a))  # 输出:4


#最小值索引 np.argmin()
print("最小值索引:", np.argmin(a))  # 输出:0 

解释:累计和(np.cumsum())和 累计积(np.cumprod())是两种逐元素的累积操作,它们分别返回数组中每个元素从头到当前元素的和或积。

2、多维数组的聚合运算

NumPy 提供了多种聚合运算,可以对数组在指定维度上进行汇总操作。这些聚合运算支持 axis 参数,可以选择在行、列或更深维度上执行。

import numpy as np

# 定义一个二维数组
a = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

# 求和
print("沿行(axis=0)求和:", np.sum(a, axis=0))    # [12, 15, 18]
print("沿列(axis=1)求和:", np.sum(a, axis=1))    # [6, 15, 24]
print("数组总和:", np.sum(a))					  # 45

# 求平均值
print("沿行(axis=0)求平均值:", np.mean(a, axis=0))  # [4, 5, 6]
print("沿列(axis=1)求平均值:", np.mean(a, axis=1))  # [2, 5, 8]
print("数组均值:", np.mean(a))                       # 5.0

# 求最大值
print("沿行(axis=0)最大值:", np.max(a, axis=0))     # [7, 8, 9]
print("沿列(axis=1)最大值:", np.max(a, axis=1))     # [3, 6, 9]
print("数组最大值:", np.max(a))						# 9

# 求最小值
print("沿行(axis=0)最小值:", np.min(a, axis=0))     # [1, 2, 3]
print("沿列(axis=1)最小值:", np.min(a, axis=1))     # [1, 4, 7]
print("数组最小值:", np.min(a))						# 1

# 求乘积
print("沿行(axis=0)求乘积:", np.prod(a, axis=0))    # [28, 80, 162]
print("沿列(axis=1)求乘积:", np.prod(a, axis=1))    # [6, 120, 504]
print("数组乘积:", np.prod(a))						# 362880

# 标准差
print("沿行(axis=0)标准差:", np.std(a, axis=0))     # [2.45, 2.45, 2.45]
print("沿列(axis=1)标准差:", np.std(a, axis=1))     # [0.82, 0.82, 0.82]
print("数组标准差:", np.std(a))						# 2.581988897471611

# 方差
print("沿行(axis=0)方差:", np.var(a, axis=0))       # [6, 6, 6]
print("沿列(axis=1)方差:", np.var(a, axis=1))       # [0.67, 0.67, 0.67]
print("数组方差:", np.var(a)) 						 # 6.666666666666667

# 中位数
print("沿行(axis=0)中位数:", np.median(a, axis=0))  # [4, 5, 6]
print("沿列(axis=1)中位数:", np.median(a, axis=1))  # [2, 5, 8]
print("数组中位数:", np.median(a))					# 5.0

# 累积和
print("沿行(axis=0)累积和:\n", np.cumsum(a, axis=0))
# [[ 1,  2,  3],
#  [ 5,  7,  9],
#  [12, 15, 18]]

print("沿列(axis=1)累积和:\n", np.cumsum(a, axis=1))
# [[ 1,  3,  6],
#  [ 4,  9, 15],
#  [ 7, 15, 24]]

print("数组累积和:\n", np.cumsum(a))
# [ 1  3  6 10 15 21 28 36 45]

# 累积积
print("沿行(axis=0)累积积:\n", np.cumprod(a, axis=0))
# [[  1,   2,   3],
#  [  4,  10,  18],
#  [ 28,  80, 162]]

print("沿列(axis=1)累积积:\n", np.cumprod(a, axis=1))
# [[  1,   2,   6],
#  [  4,  20, 120],
#  [  7,  56, 504]]

print("数组累积积:\n", np.cumprod(a))
# [     1      2      6     24    120    720   5040  40320 362880]

# 最大值索引
print("沿行(axis=0)最大值索引:", np.argmax(a, axis=0))  # [2, 2, 2]
print("沿列(axis=1)最大值索引:", np.argmax(a, axis=1))  # [2, 2, 2]
print("数组最大值索引:", np.argmax(a))					  # 8

# 最小值索引
print("沿行(axis=0)最小值索引:", np.argmin(a, axis=0))  # [0, 0, 0]
print("沿列(axis=1)最小值索引:", np.argmin(a, axis=1))  # [0, 0, 0]
print("数组最小值索引:", np.argmin(a))					  # 0

解释

  • axis=0 表示沿着行方向聚合(计算每一列的聚合结果)。
  • axis=1 表示沿着列方向聚合(计算每一行的聚合结果)。
  • 不指定 axis 则对整个数组进行运算,返回一个单一的值。
  • 对于 3D 数组或更高维度的数组,可以选择任意一个轴进行聚合。例如,对于一个 3x3x3 数组,可以指定 axis=0axis=1axis=2

4.7.广播机制

在 NumPy 中,广播(Broadcasting)机制用于处理不同形状的数组之间的算术运算。当两个数组的形状不同,但符合某些条件时,NumPy 会自动将较小数组的形状扩展为与较大数组相同的形状,以便进行逐元素运算,而无需复制数据。

广播机制的规则

广播机制遵循以下规则:

  1. 如果两个数组的维度不同,则在较小维度的前面填充1,直到两个数组的维数相同。例如,形状为 (3, ) 的数组会被当成 (1, 3)

  2. 如果两个数组的形状在任何一个维度上不匹配,则其中一个维度必须为1。这种情况下,NumPy 会在那个维度上将大小为1的数组“扩展”以匹配另一个数组。例如,形状为 (4, 3)(1, 3) 的数组可以进行广播,因为第一个数组在第一个维度是4,第二个数组在第一个维度是1。

  3. 如果两个数组在任一维度上都不相等且没有1,则无法广播,会产生错误。

广播的示例

  1. 数组与标量的广播

当数组和标量进行运算时,标量会自动扩展为与数组相同的形状。

import numpy as np

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

# 标量 2 被广播为与 a 相同形状的数组 [2, 2, 2]
result = a + b
print(result)  # 输出:[3, 4, 5]
  1. 不同维度的数组广播
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([1, 2, 3])

# b 的形状为 (3,),会先扩展为(1,3),然后广播为 (2, 3) 以匹配 a 的形状
result = a + b
print(result)
# 输出:
# [[2, 4, 6],
#  [5, 7, 9]]
  1. 更复杂的广播
a = np.array([1, 2, 3]).reshape(3, 1)
b = np.array([4, 5, 6])

# a 的形状是 (3, 1),b 的形状是 (3,)被扩展成(1,3)
# a 会被广播为 (3, 3),b 会被广播为 (3, 3)
result = a + b
print(result)
# 输出:
# [[5, 6, 7],
#  [6, 7, 8],
#  [7, 8, 9]]
  1. 广播失败的情况
    如果两个数组无法满足广播机制的规则,会抛出错误。例如:
a = np.array([1, 2, 3])
b = np.array([1, 2])

# 这会产生错误,因为数组 a 的形状是 (3,) 而 b 的形状是 (2,)
# 无法在任一维度上进行广播
result = a + b  # ValueError

4.8.数学函数

在 NumPy 中,提供了多种数学函数,可以对数组进行基本的数学运算,这些函数支持逐元素操作,且通常能自动应用广播机制,使得不同形状的数组也能进行计算。

函数 说明 示例
np.abs() 绝对值 np.abs([-1, -2, 3])
np.sqrt() 平方根 np.sqrt([4, 9, 16])
np.exp() 指数运算(e 的幂次) np.exp([1, 2, 3])
np.log() 自然对数(ln) np.log([1, np.e, np.e**2])
np.log10() 以 10 为底的对数 np.log10([10, 100, 1000])
np.power() 幂运算 np.power([2, 3, 4], 2)
np.sin() 正弦 np.sin([0, np.pi/2, np.pi])
np.cos() 余弦 np.cos([0, np.pi/2, np.pi])
np.tan() 正切 np.tan([0, np.pi/4, np.pi/2])
np.arcsin() 反正弦 np.arcsin([0, 0.5, 1])
np.arccos() 反余弦 np.arccos([1, 0.5, 0])
np.arctan() 反正切 np.arctan([0, 1, np.inf])
np.sinh() 双曲正弦 np.sinh([0, 1, 2])
np.cosh() 双曲余弦 np.cosh([0, 1, 2])
np.tanh() 双曲正切 np.tanh([0, 1, 2])
np.floor() 向下取整 np.floor([1.7, 2.3, 3.8])
np.ceil() 向上取整 np.ceil([1.2, 2.8, 3.1])
np.round() 四舍五入 np.round([1.5, 2.3, 3.7])

常见数学函数示例:

import numpy as np

# 示例数组
a = np.array([1, 2, 3, 4])
b = np.array([0.5, 1.5, 2.5, 3.5])

# 1. 绝对值
print("绝对值 np.abs(a):", np.abs(a))	#[1 2 3 4]

# 2. 平方根
print("平方根 np.sqrt(a):", np.sqrt(a))#[1.         1.41421356 1.73205081 2.        ]

# 3. 指数运算(e 的幂次方)
print("指数运算 np.exp(a):", np.exp(a))#[ 2.71828183  7.3890561  20.08553692 54.59815003]

# 4. 自然对数(ln)
print("自然对数 np.log(a):", np.log(a))# [0.         0.69314718 1.09861229 1.38629436]

# 5. 对数运算(以 10 为底)
print("对数运算(以 10 为底)np.log10(a):", np.log10(a))#[0.         0.30103    0.47712125 0.60205999]

# 6. 幂运算
print("幂运算 np.power(a, 3):", np.power(a, 3))#[ 1  8 27 64]

# 7. 三角函数
print("正弦 np.sin(b):", np.sin(b))# [ 0.47942554  0.99749499  0.59847214 -0.35078323]
print("余弦 np.cos(b):", np.cos(b))#[ 0.87758256  0.0707372  -0.80114362 -0.93645669]
print("正切 np.tan(b):", np.tan(b))#[ 0.54630249 14.10141995 -0.7470223   0.37458564]

# 8. 反三角函数
print("反正弦 np.arcsin(b / 4):", np.arcsin(b / 4))  # 将值归一化到 [-1, 1] 范围
print("反余弦 np.arccos(b / 4):", np.arccos(b / 4))
print("反正切 np.arctan(b):", np.arctan(b))

# 9. 双曲函数
print("双曲正弦 np.sinh(b):", np.sinh(b))
print("双曲余弦 np.cosh(b):", np.cosh(b))
print("双曲正切 np.tanh(b):", np.tanh(b))

# 10. 舍入函数
print("向下取整 np.floor(b):", np.floor(b))#[0. 1. 2. 3.]
print("向上取整 np.ceil(b):", np.ceil(b))#[1. 2. 3. 4.]
print("四舍五入 np.round(b):", np.round(b))#[0. 2. 2. 4.]必须大于x.5才会变成x+1.(x为任意数)

5、数组索引与切片

在 NumPy 中,数组索引和切片用于访问和修改数组中的元素、子数组,支持对多维数组进行灵活的选择和操作。以下是数组索引和切片的基本方法和示例。

5.1. 普通索引

对于一维数组,可以使用与 Python 列表类似的索引方式:

import numpy as np

a = np.array([10, 20, 30, 40, 50])

# 访问第一个元素
print("第一个元素:", a[0])#第一个元素: 10

# 访问最后一个元素
print("最后一个元素:", a[-1])#最后一个元素: 50

对于二维或更高维数组,可以使用逗号分隔的索引来访问特定元素。

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

# 访问第一行第二列的元素
print("第一行第二列的元素:", b[0, 1])#第一行第二列的元素: 2

# 访问最后一行最后一列的元素
print("最后一行最后一列的元素:", b[-1, -1])#最后一行最后一列的元素: 9

5.2. 布尔索引

布尔索引是一种通过布尔条件来选择数组中满足条件的元素的方式。在 NumPy 中,可以使用布尔数组或布尔条件来筛选数组中的元素。

1.使用布尔条件筛选
我们可以对数组应用条件表达式,得到一个布尔数组,然后用这个布尔数组来选择满足条件的元素。

import numpy as np

# 创建一个示例数组
a = np.array([10, 15, 20, 25, 30])

# 筛选出所有大于 20 的元素
result = a[a > 20]
print("大于 20 的元素:", result)#大于 20 的元素: [25 30]

在这个例子中,a > 20 生成了一个布尔数组 [False, False, False, True, True],然后 a[a > 20] 使用该布尔数组从原数组中筛选出 2530

2.多条件筛选
可以使用逻辑运算符 &(和)、|(或)等来组合多个条件。

# 筛选出大于 15 且小于 30 的元素
result = a[(a > 15) & (a < 30)]
print("大于 15 且小于 30 的元素:", result)#大于 15 且小于 30 的元素: [20 25]

3.布尔数组作为索引
也可以直接创建一个布尔数组用于索引。这种方式对于需要用固定的布尔模式筛选元素的情况非常方便。

# 创建一个布尔数组
bool_index = np.array([True, False, True, False, True])

# 使用布尔数组索引
result = a[bool_index]
print("通过布尔数组筛选的元素:", result)#通过布尔数组筛选的元素: [10 20 30]

这里,布尔数组 [True, False, True, False, True] 用来选择 a 中的第 0、2 和 4 个元素。

4.修改满足条件的元素
布尔索引也可以用于修改满足条件的元素。

# 将所有小于 20 的元素修改为 0
a[a < 20] = 0
print("小于 20 的元素修改为 0 后的数组:", a)#小于 20 的元素修改为 0 后的数组: [ 0  0 20 25 30]

5. 布尔索引在多维数组中的应用
布尔索引同样适用于多维数组。条件表达式会返回一个形状相同的布尔数组,用于选择多维数组中的特定元素。

# 创建一个二维数组
b = np.array([[10, 15, 20], [25, 30, 35], [40, 45, 50]])

# 筛选出二维数组中大于 30 的元素
result = b[b > 30]
print("二维数组中大于 30 的元素:", result)#二维数组中大于 30 的元素: [35 40 45 50]

布尔索引是一种强大的方式,可以快速筛选和修改数组中的元素。它使得条件筛选和修改数组更加简洁、灵活。

5.3. 花式索引

普通索引用一层中括号,花式索引用两层中括号。花式索引允许通过数组的索引列表选取特定位置的元素。

# 创建一个示例一维数组
a = np.array([10, 20, 30, 40, 50])

# 使用索引数组 [0, 2, 4] 选取特定位置的元素
print("特定位置的元素:", a[[0, 2, 4]])#特定位置的元素: [10 30 50]


# 创建一个示例二维数组
b = np.array([[10, 20, 30],
              [40, 50, 60],
              [70, 80, 90]])

# 使用行索引和列索引选择元素
# 选择位置为 (0, 1), (1, 2), (2, 0) 的元素
row_indices = [0, 1, 2]
col_indices = [1, 2, 0]

result = b[row_indices, col_indices]
print("使用花式索引选择的元素:", result)#使用花式索引选择的元素: [20 60 70]

注意

  1. 索引数组的长度相同:在花式索引中,行索引数组和列索引数组的长度必须相同。
  2. 返回一维数组:花式索引会返回一个一维数组,包含了选择的元素。
  3. 支持多维数组:花式索引不仅适用于二维数组,还可以用于更高维的数组。

5.4. 数组切片

NumPy 数组支持切片操作,允许选择连续的子数组,使用语法 array[start:stop:step]

语法 array[start:stop:step]参数含义:

  • start:切片的起始索引(包含)。如果省略,则默认为数组的第一个元素。

  • stop:切片的终止索引(不包含)。切片会取到 stop - 1 索引的元素。如果省略,则默认为数组的最后一个元素。

  • step:切片的步长(间隔)。如果省略,则默认为 1。

一维数组切片

c = np.array([10, 20, 30, 40, 50])

# 从索引 1 到索引 3 的元素
print("切片 [1:4]:", c[1:4])#切片 [1:4]: [20 30 40]

# 每隔一个元素取一个值
print("切片 [::2]:", c[::2])#切片 [::2]: [10 30 50]

多维数组切片

切片语法 array[start:stop:step] 可以在多维数组中应用,通过逗号分隔每个维度的切片。

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

# 选取第 1 至第 2 行的所有列
print("第 1 至第 2 行的所有列:", d[0:2, :])#第 1 至第 2 行的所有列: [[1 2 3]
										#	                    [4 5 6]]
# 选取第 1 至第 2 列的所有行
print("第 1 至第 2 列的所有行:", d[:, 0:2])#第 1 至第 2 列的所有行: [[1 2]
										#                       [4 5]
										#                       [7 8]]

# 从第二行开始选取每隔一行的元素
print("隔行选取每隔一列的元素:", d[1::2, ::2])#隔行选取每隔一列的元素: [[4 6]]

5.5. 修改数组元素

在 NumPy 中,我们可以通过索引和切片来修改数组中的元素。以下是一些常见的方法来修改数组元素:

1. 使用单个索引修改元素

可以直接使用索引来访问并修改单个元素。

import numpy as np

# 创建一个一维数组
a = np.array([1, 2, 3, 4, 5])

# 修改索引 2 的元素
a[2] = 10
print("修改后的数组:", a) #修改后的数组: [ 1  2 10  4  5]

2. 使用切片修改一部分元素

可以通过切片选择数组中的多个元素,并对它们进行批量修改。

# 修改索引 1 到 3 的元素(不包括 3)
a[1:3] = [20, 30]
print("切片修改后的数组:", a) #切片修改后的数组: [ 1 20 30  4  5]

3. 使用布尔索引修改元素

布尔索引可以用来选择满足某些条件的元素,并对这些元素进行修改。

# 修改数组中大于 10 的元素,将它们设置为 100
a[a > 10] = 100
print("布尔索引修改后的数组:", a) #布尔索引修改后的数组: [  1 100 100   4   5]

4. 多维数组元素的修改

对于多维数组,可以使用行和列的索引或切片来选择特定的元素或子数组进行修改。

# 创建一个二维数组
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 修改第 0 行第 1 列的元素
b[0, 1] = 20

# 修改第 1 行的所有元素
b[1, :] = [40, 50, 60]

print("多维数组修改后的数组:\n", b)
#多维数组修改后的数组:
# [[ 1 20  3]
#  [40 50 60]
#  [ 7  8  9]]

5. 使用np.where()进行条件修改

np.where() 通过条件找到索引位置,然后修改这些位置的元素。这通常在需要灵活设置不同值时会更方便。

# 将数组中所有大于 5 的元素设为 0
a[np.where(a > 5)] = 0
print("使用 np.where 修改后的数组:", a)#使用 np.where 修改后的数组:[ 1  0  0  4  5]

6. 使用 np.put 修改指定位置的元素

  • numpy.put(a, ind, v, mode='raise')
    
    • a: 输入数组,您希望在其中修改元素。
    • ind: 需要修改的元素的索引,可以是一个整数或整数数组。
    • v: 新的值,可以是一个标量或与 ind 相同形状的数组。
    • mode: (可选)决定如何处理索引超出范围的情况。默认值为 'raise',这意味着如果索引超出范围,将引发错误。另一个选项是 'wrap',它会将超出范围的索引循环回数组的开头。
  • 一维数组的用法

    下面是一个基本示例,展示如何使用 np.put() 来修改数组中的特定元素。

    import numpy as np
    
    # 创建一个一维数组
    arr = np.array([10, 20, 30, 40, 50])
    
    # 使用 np.put 修改索引 1 和 3 的元素
    np.put(arr, [1, 3], [100, 200])
    print("使用 np.put 修改后的数组:", arr)#使用 np.put 修改后的数组: [ 10 100  30 200  50]
    

    在这个例子中,np.put() 函数在索引 1 和 3 的位置上分别替换了数组的元素,将其修改为 100 和 200。

  • 多维数组的用法

    np.put() 也可以用于多维数组,但在这种情况下,它会展平数组(将其视为一维数组)并按顺序处理索引。

    # 创建一个二维数组
    arr2d = np.array([[1, 2, 3], [4, 5, 6]])
    
    # 使用 np.put 修改元素
    np.put(arr2d, [0, 3], [10, 20])
    print("二维数组使用 np.put 修改后的数组:\n", arr2d)
    #二维数组使用 np.put 修改后的数组:
    # [[10  2  3]
    # [20  5  6]]
    

    在这个例子中,np.put() 将元素 [1, 4] 修改为 [10, 20]。注意,数组被视为一个一维数组,因此索引 0 和 3 分别对应于元素 1 和 4。

  • 处理超出范围的索引

    如果指定的索引超出了数组的范围,np.put() 默认会引发错误。

    # 创建一个数组
    arr = np.array([1, 2, 3])
    
    # 尝试使用超出范围的索引
    try:
        np.put(arr, [0, 5], [10, 20])  # 索引 5 超出范围
    except IndexError as e:
        print("错误信息:", e)
    #错误信息: index 5 is out of bounds for axis 0 with size 3
    
  • 使用 mode 参数

    可以使用 mode 参数来控制超出范围的行为。

    # 使用 'wrap' 模式
    arr = np.array([1, 2, 3, 4, 5])
    np.put(arr, [0, 5], [10, 20], mode='wrap')  # 索引 5 会循环到 0
    print("使用 wrap 模式后的数组:", arr)#使用 wrap 模式后的数组: [20  2  3  4 10]
    

    在这个例子中,索引 5 循环回到 0,因此元素 20 被放置在数组的第一个位置。

5.6.数组赋值

在 NumPy 中,数组赋值的确有时只是绑定(reference),而不是创建一个新的数组副本。理解这一点非常重要,因为它直接影响到对数组的操作及其可能产生的副作用。

1、直接赋值

当你将一个数组赋值给另一个变量时,两个变量将引用同一个数组,而不是创建一个新的数组副本。

import numpy as np

# 创建一个数组
a = np.array([1, 2, 3, 4, 5])

# 将数组 a 赋值给 b
b = a

# 修改 b 中的元素
b[0] = 10

print("a 数组:", a)  # a 也会改变
print("b 数组:", b)  # b 的修改反映在 a 上
#a 数组: [10  2  3  4  5]
#b 数组: [10  2  3  4  5]

在这个例子中,b 只是对 a 的一个引用,因此对 b 的修改也会影响到 a

2、np.copy()赋值

为了避免这种绑定的行为,可以使用 np.copy() 创建一个数组的副本。副本是一个新的数组,修改副本不会影响原始数组。

# 使用 np.copy 创建 a 的副本
c = np.copy(a)

# 修改 c 中的元素
c[1] = 20

print("a 数组:", a)  # a 不会改变
print("c 数组:", c)  # c 的修改不影响 a
#a 数组: [10  2  3  4  5]
#c 数组: [10 20  3  4  5]

3、总结

  • 赋值是引用:在 NumPy 中,赋值操作通常是对数组的引用,这意味着两个变量指向同一个数据存储区域。
  • 使用 np.copy():如果希望创建一个独立的副本,可以使用 np.copy(),这样对副本的修改将不会影响原始数组。
  • 谨慎处理:在进行数组赋值时,需小心处理引用,以避免意外修改数据。

6、数组的变形

在 NumPy 中,数组的变形操作包含多种方法,可以实现转置、翻转、重塑、拼接和分裂。以下是这几种常用变形操作的具体方法和示例:

6.1. 数组的转置

转置操作会将数组的行和列互换。NumPy 提供了 transpose()T 属性、swapaxes() 等方法可以来实现转置。以下是对每个方法的详细说明及示例。

1. transpose()

功能
transpose() 函数用于交换数组的维度顺序。对于二维数组,它等效于矩阵的转置操作(交换行和列);对于多维数组,它可以调整维度的顺序,形成不同排列。

语法

numpy.transpose(arr, axes=None)
  • 参数

    • arr:需要转置的数组。
    • axes:指定维度的顺序(可选)。如果没有提供,维度会被反转。
  • 返回值:返回一个新数组,该数组是输入数组维度的重新排列视图。

示例:

  1. 二维数组的转置:

    import numpy as np
    
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    transposed_arr = np.transpose(arr)
    
    print("原始数组:\n", arr)
    print("转置后的数组:\n", transposed_arr)
    

    输出

    原始数组:
    [[1 2 3]
     [4 5 6]]
    转置后的数组:
    [[1 4]
     [2 5]
     [3 6]]
    
  2. 多维数组指定轴的交换:

    arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
    transposed_arr3d = np.transpose(arr3d, (1, 0, 2))
    
    print("原始数组:\n", arr3d)
    print("转置后的数组 (指定维度顺序):\n", transposed_arr3d)
    

    输出

    原始数组:
    [[[1 2]
      [3 4]]
    
     [[5 6]
      [7 8]]]
    转置后的数组 (指定维度顺序):
    [[[1 2]
      [5 6]]
    
     [[3 4]
      [7 8]]]
    

2.T 属性

功能
T 属性是 NumPy 中用于转置数组的快捷方式,专门用于二维数组的行列互换操作。它不支持多维数组的维度重新排列,仅对数组的最后两个轴进行交换。

语法

arr.T
  • 参数:无

  • 返回值:返回一个转置后的数组(视图)。

示例:

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

print("原始数组:\n", arr)
print("使用 T 属性转置后的数组:\n", transposed_arr_T)

输出

原始数组:
[[1 2 3]
 [4 5 6]]
使用 T 属性转置后的数组:
[[1 4]
 [2 5]
 [3 6]]

说明

  • T 仅在二维数组上生效,效果和 transpose() 类似。
  • T 属性比 transpose() 更简洁,适合只需要基本转置操作的场景。

3. swapaxes()

功能
swapaxes() 用于交换多维数组的两个指定轴。与 transpose() 不同,它不会改变所有轴的顺序,仅交换指定的两个轴,这对于高维数组的轴转换操作非常灵活。

语法

numpy.swapaxes(arr, axis1, axis2)
  • 参数

    • arr:输入数组。
    • axis1:要交换的第一个轴。
    • axis2:要交换的第二个轴。
  • 返回值:返回一个新的数组(视图),交换了指定轴。

示例:

  1. 二维数组的轴交换:

    arr2d = np.array([[1, 2, 3], [4, 5, 6]])
    swapped_arr2d = arr2d.swapaxes(0, 1)
    
    print("原始数组:\n", arr2d)
    print("交换轴后的数组:\n", swapped_arr2d)
    

    输出:

    原始数组:
    [[1 2 3]
     [4 5 6]]
    交换轴后的数组:
    [[1 4]
     [2 5]
     [3 6]]
    
  2. 三维数组的轴交换:

    arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
    swapped_arr3d = arr3d.swapaxes(0, 2)
    
    print("原始数组:\n", arr3d)
    print("交换轴后的数组:\n", swapped_arr3d)
    

    输出:

    原始数组:
    [[[1 2]
      [3 4]]
    
     [[5 6]
      [7 8]]]
    交换轴后的数组:
    [[[1 5]
      [3 7]]
    
     [[2 6]
      [4 8]]]
    

说明

  • swapaxes() 是针对多维数组非常灵活的轴交换方法,适用于只想交换特定两个维度的场景。
  • swapaxes() 可以实现复杂的轴重排,而不需要重新组织所有轴顺序。

4.总结对比

方法 适用情况 功能 语法示例
transpose() 二维或多维数组 可以交换多个维度顺序,形成任意顺序的排列 np.transpose(arr)
T 属性 二维数组 快捷实现二维数组的转置,仅用于行列互换 arr.T
swapaxes() 二维或多维数组 交换指定的两个轴,适合高维数组中单独交换两维的情况 arr.swapaxes(0, 1)

6.2.数组的翻转

在 NumPy 中,数组的反转(reversing an array)指的是将数组的元素顺序进行翻转。反转可以在不同的维度上进行,例如沿着行、列或特定的轴反转数组。这对于数据处理、分析以及在图像处理等领域中非常有用。

1.np.flip()

np.flip() 函数用于沿指定轴反转数组。如果未指定轴,将反转所有维度上的顺序。

语法np.flip(arr, axis=None)

  • arr:要反转的数组。
  • axis:指定沿哪个轴反转。默认为 None,即所有轴都反转。

示例

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
# 沿行反转 (轴=0)
print(np.flip(arr, axis=0))  
# 输出:
# [[4 5 6]
#  [1 2 3]]

# 沿列反转 (轴=1)
print(np.flip(arr, axis=1))  
# 输出:
# [[3 2 1]
#  [6 5 4]]

2. np.flipud()np.fliplr()

这些是 np.flip() 的简化版本,专门用于二维数组的行或列方向反转。

  • np.flipud():沿垂直轴(上下)反转,类似于 np.flip(arr, axis=0)
  • np.fliplr():沿水平轴(左右)反转,类似于 np.flip(arr, axis=1)

示例

# 上下翻转
print(np.flipud(arr))
# 输出:
# [[4 5 6]
#  [1 2 3]]

# 左右翻转
print(np.fliplr(arr))
# 输出:
# [[3 2 1]
#  [6 5 4]]

3.使用切片 [::-1] 进行反转

使用切片 [::-1] 可以在数组的特定维度上实现反转。

示例

# 一维数组反转
arr1d = np.array([1, 2, 3, 4])
print(arr1d[::-1])  # 输出: [4 3 2 1]

# 二维数组行反转(等同于 np.flip(arr, axis=0))
print(arr[::-1])
# 输出:
# [[4 5 6]
#  [1 2 3]]

# 二维数组列反转
print(arr[:, ::-1])
# 输出:
# [[3 2 1]
#  [6 5 4]]

4.高维数组的反转

对于高维数组,np.flip() 也可以指定轴,以便在不同维度上进行反转。

示例

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

# 沿第 0 轴反转
print(np.flip(arr3d, axis=0))
# 输出:
# [[[5 6]
#   [7 8]]
#
#  [[1 2]
#   [3 4]]]

# 沿第 1 轴反转
print(np.flip(arr3d, axis=1))
# 输出:
# [[[3 4]
#   [1 2]]
#
#  [[7 8]
#   [5 6]]]

# 沿第 2 轴反转
print(np.flip(arr3d, axis=2))
# 输出:
# [[[2 1]
#   [4 3]]
#
#  [[6 5]
#   [8 7]]]

总结

方法 描述 示例
np.flip(arr, axis=0) 沿指定轴翻转(所有维度反转) np.flip(arr, axis=0)
np.flipud(arr) 沿垂直方向(上下)反转 np.flipud(arr)
np.fliplr(arr) 沿水平方向(左右)反转 np.fliplr(arr)
[::-1] 使用切片反转一维数组或特定轴上的元素顺序 arr[::-1], arr[:, ::-1]

这些反转方法可以帮助高效、灵活地调整数组元素顺序,从而在多种场景中满足数据处理需求。

6.3. 数组的重塑

数组的重塑(reshape)是指将一个数组重新组织成不同的形状,而不改变数据的本质。NumPy 提供了多种重塑数组的方式,这对于数据分析和机器学习任务中的数据处理很有用。

1. 使用 reshape() 方法

reshape() 方法可以将数组重新定义为指定的形状,只要新形状的元素总数与原数组相同。其常见语法是 array.reshape(new_shape)

示例

import numpy as np

# 创建一个一维数组
arr = np.array([1, 2, 3, 4, 5, 6])

# 将其重塑为 2x3 的二维数组
reshaped_arr = arr.reshape(2, 3)
print(reshaped_arr)
# 输出:
# [[1 2 3]
#  [4 5 6]]

2. 自动推断维度:-1

使用 -1 作为 reshape() 中的某个维度,NumPy 会自动计算该维度的大小,使得新数组的总大小与原数组一致。适合用于未知维度的数据重塑。

示例

# 自动推断行数,使数组为 3 列
reshaped_arr1 = arr.reshape(-1, 3)
print(reshaped_arr1)
# 输出:
# [[1 2 3]
#  [4 5 6]]

# 自动推断行数,使数组为 3 行
reshaped_arr2 = arr.reshape(3, -1)
print(reshaped_arr2)
print(arr)
# 输出:
#[[1 2]
# [3 4]
# [5 6]]
#[1 2 3 4 5 6]

3.np.resize() 方法

resize() 不同于 reshape(),它不受元素总数限制,会直接更改数组的形状并填充或删除数据以满足新形状需求。若元素不足,会循环填充;多余元素会被截断。

示例

# 改变形状为 2x4(比原数组多了两个元素)
resized_arr = np.resize(arr, (2, 4))
print(resized_arr)
print(arr)
# 输出:
# [[1 2 3 4]
#  [5 6 1 2]]
# [1 2 3 4 5 6]

4. ravel()flatten() 方法

  • ravel():返回一个展开的一维数组,是原数组的“视图”。
  • flatten():返回一个展开的一维数组,是原数组的“副本”。

示例

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

# 使用 ravel() 展开
print(arr2d.ravel())  # 输出: [1 2 3 4 5 6]

# 使用 flatten() 展开
print(arr2d.flatten())  # 输出: [1 2 3 4 5 6]

视图和副本

  • 视图(View)

    当我们创建一个数组的“视图”时,它与原数组共享相同的数据内存。即使数组形状或视图方式不同,视图中的任何更改会直接反映在原数组上。视图是原数组的另一种“窗口”,并没有复制数据。

    • 示例

      import numpy as np
      
      arr = np.array([1, 2, 3, 4, 5])
      view_arr = arr[:3]  # 创建前3个元素的视图
      view_arr[0] = 100   # 修改视图中的第一个元素
      print(arr)          # 输出:[100, 2, 3, 4, 5]
      

      在此示例中,对 view_arr 的更改也会影响到 arr,因为它们共享数据内存。

    • 常见的视图创建方式:切片操作(arr[start:stop:step])、ravel()(在适当情况下)、reshape()(在适当情况下)等。

  • 副本(Copy)

    当我们创建一个数组的“副本”时,NumPy 会生成一个新的数组对象,并分配独立的数据内存。副本中的任何更改不会影响原数组。

    • 示例

      arr = np.array([1, 2, 3, 4, 5])
      copy_arr = arr[:3].copy()  # 创建前3个元素的副本
      copy_arr[0] = 100          # 修改副本中的第一个元素
      print(arr)                 # 输出:[1, 2, 3, 4, 5]
      

      在此示例中,修改 copy_arr 的值不会影响到原数组 arr

    • 常见的副本创建方式copy() 函数、flatten() 等。

  • 何时使用“视图”与“副本”

    • 视图:节省内存,不需要数据独立时适用,例如在切片数组时,避免创建额外数据。

    • 副本:适用于需要独立数据、不会影响原数组的场景,如在独立的数据处理或分析时。

5.reshape() 中的 order 参数

reshape() 中的 order 参数控制重塑顺序:

  • C:按行重塑(默认)
  • F:按列重塑
  • A:根据内存中的数组布局选择

示例

# 按列重塑为 3x2 数组
reshaped_f_order = arr.reshape(3, 2, order='F')
print(reshaped_f_order)
# 输出:
# [[1 4]
#  [2 5]
#  [3 6]]

6.总结

方法 描述 示例用法
reshape(new_shape) 将数组重塑为指定形状,新形状的元素总数必须等于原数组总数。 arr.reshape(2, 3)
reshape(-1, n) 使用 -1 自动推断某个维度,使得总元素数不变。 arr.reshape(-1, 3)
np.resize(new_shape) 更改数组形状,不受元素总数限制。若元素不足,会循环填充;多余元素会被截断。 np.resize(arr, (2, 4))
ravel() 展开为一维数组,返回的是原数组的视图。 arr2d.ravel()
flatten() 展开为一维数组,返回的是原数组的副本。 arr2d.flatten()
reshape(new_shape, order='C') 按行重塑(默认,C 风格);也可用 order='F' 按列重塑或 order='A' 根据内存布局选择。 arr.reshape(3, 2, order='F')

这些方法让数组变形更加灵活,以适应不同维度和场景的需求。


6.4. 数组的拼接

数组的拼接是指将多个数组沿指定轴连接成一个新的数组。NumPy 提供了多种方法来进行数组的拼接,常见的有 concatenate()stack()hstack()vstack()dstack()

1. np.concatenate()

concatenate() 可以沿指定的轴拼接多个数组,数组的维度必须一致

  • 语法np.concatenate((arr1, arr2, ...), axis=0)
  • 参数axis 指定拼接轴,默认 axis=0(沿行方向)。

示例

对于一维数组:

import numpy as np

# 创建两个一维数组
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])

# 沿行方向拼接
result = np.concatenate((arr1, arr2))
print(result)  # 输出: [1 2 3 4 5 6]
#np.concatenate()函数在处理一维数组时,确实不能沿列方向进行拼接,因为一维数组本身没有列的概念。

对于二维数组:

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

# 沿行方向拼接(axis=0)
result = np.concatenate((arr1, arr2), axis=0)
# 输出:
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

# 沿列方向拼接(axis=1)
result = np.concatenate((arr1, arr2), axis=1)
# 输出:
# [[1 2 5 6]
#  [3 4 7 8]]

2. np.stack()

stack() 用于沿新轴拼接数组,生成一个新的高维数组。要求数组的形状必须完全相同

  • 语法np.stack((arr1, arr2, ...), axis=0)
  • 参数axis 指定新的拼接轴位置,默认 axis=0(沿行方向)。

示例

1.一维数组示例:

import numpy as np

arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
#axis=0 沿第一个轴(在一维数组中会创建一个二维数组)
result = np.stack((arr1, arr2), axis=0)
print(result)
# 输出:
# [[1 2 3]
#  [4 5 6]]
# 形状: (2, 3)

#axis=1 沿第二个轴堆叠(在一维数组中会创建一个二维数组)
result = np.stack((arr1, arr2), axis=1)
print(result)
# 输出:
# [[1 4]
#  [2 5]
#  [3 6]]
# 形状: (3, 2)

在这里,axis=0 表示 np.stack() 会在最外层创建一个新维度,形成一个二维数组。axis=1 表示 np.stack() 会在第二个轴的位置插入新维度,形成一个二维数组,每个元素被按列堆叠。

2.二维数组的示例

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

#axis=0 沿第一个轴(生成形状为 (2, 2, 3) 的三维数组)
result = np.stack((arr1, arr2), axis=0)
print(result)
# 输出:
# [[[ 1  2  3]
#   [ 4  5  6]]
#
#  [[ 7  8  9]
#   [10 11 12]]]
# 形状: (2, 2, 3)

#axis=1 沿第二个轴(生成形状为 (2, 2, 3) 的三维数组)
result = np.stack((arr1, arr2), axis=1)
print(result)
# 输出:
# [[[ 1  2  3]
#   [ 7  8  9]]
#
#  [[ 4  5  6]
#   [10 11 12]]]
# 形状: (2, 2, 3)

#axis=2 沿第三个轴(生成形状为 (2, 3, 2) 的三维数组)
result = np.stack((arr1, arr2), axis=2)
print(result)
# 输出:
# [[[ 1  7]
#   [ 2  8]
#   [ 3  9]]
#
#  [[ 4 10]
#   [ 5 11]
#   [ 6 12]]]
# 形状: (2, 3, 2)

在此例中,axis=0arr1arr2 放置在新数组的第一个维度。axis=1 表示在第二个轴的位置插入新维度,使数组沿行方向逐个堆叠。axis=2 将数组沿列方向逐个堆叠,生成了一个新的三维数组。


3. np.hstack()np.vstack()

  • hstack():沿水平方向(行方向)拼接数组,等价于 concatenate()axis=1 的情况。
  • vstack():沿垂直方向(列方向)拼接数组,等价于 concatenate()axis=0 的情况。

示例

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

# 水平方向拼接
result1 = np.hstack((arr1, arr2))
print(result1)  # 输出: [1 2 3 4 5 6]
# 垂直方向拼接
result2 = np.vstack((arr1, arr2))
print(result2)
# 输出:
#[[1 2 3]
# [4 5 6]]


arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
# 水平方向拼接
result3 = np.hstack((arr1, arr2))
print(result3)
# 输出:
#[[1 2 5 6]
# [3 4 7 8]]
# 垂直方向拼接
result4 = np.vstack((arr1, arr2))
print(result4)
# 输出:
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

4. np.dstack()

dstack() 沿深度方向(第三维)拼接数组,适用于二维数组。

示例

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

result = np.dstack((arr1, arr2))
# 输出:
# [[[1 5]
#   [2 6]]
#
#  [[3 7]
#   [4 8]]]

5. np.column_stack()np.row_stack()

  • column_stack():将一维数组作为列堆叠成二维数组,或沿列方向拼接二维数组。
  • row_stack():将一维数组作为行堆叠成二维数组。
  • 它们主要是为一维和二维数组设计的,尽管在某些情况下它们可以用于三维及更高维数组,但这并不是它们的主要用途。

示例

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

# 列堆叠
result = np.column_stack((arr1, arr2))
# 输出:
# [[1 4]
#  [2 5]
#  [3 6]]

# 行堆叠(等同于 vstack)
result = np.row_stack((arr1, arr2))
# 输出:
# [[1 2 3]
#  [4 5 6]]

6.总结

方法 描述
np.concatenate() 沿指定轴拼接数组
np.stack() 沿新的轴拼接数组,生成一个新的高维数组
np.hstack() 沿水平方向(列)拼接数组
np.vstack() 沿垂直方向(行)拼接数组
np.dstack() 沿深度方向(第三维)拼接数组
np.column_stack() 将一维数组作为列堆叠成二维,或沿列方向拼接
np.row_stack() 将一维数组作为行堆叠成二维,等同于 vstack()

这些方法帮助将数组按不同维度进行拼接,适用于多种数据结构。

6.5. 数组的分裂

数组的分裂(或拆分)是将一个数组分割成多个子数组的过程。NumPy 提供了几种常用的数组分裂方法,主要包括 np.split()np.array_split()np.hsplit()np.vsplit()np.dsplit()

1.np.split()

split() 将数组沿指定的轴分成相等的部分。如果数组无法均匀分割,会报错。

  • 语法np.split(arr, indices_or_sections, axis=0)
  • 参数
    • arr:待分割的数组。
    • indices_or_sections:整数(将数组分成几部分)或整数列表(指定分割的索引位置)。
    • axis:沿哪个轴进行分割,默认为 0(沿行方向)。

示例

对于一维数组:

import numpy as np

arr = np.array([1, 2, 3, 4, 5, 6])
result = np.split(arr, 3)  # 将数组分成 3 份
print(result)
# 输出:
# [array([1, 2]), array([3, 4]), array([5, 6])]

对于二维数组:

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
result = np.split(arr, 2, axis=0)  # 沿行分成 2 份
# 输出:
# [array([[ 1,  2,  3],
#        [ 4,  5,  6]]),
#  array([[ 7,  8,  9],
#        [10, 11, 12]])]

2. np.array_split()

array_split() 允许数组在不能均匀分割时,尽量均匀地分成尽可能相等的部分。它适用于任何分割情况。

  • 语法np.array_split(arr, indices_or_sections, axis=0)

示例

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

在二维数组中:

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
result = np.array_split(arr, 2, axis=1)  # 沿列方向分成 2 份
# 输出:
# [array([[1, 2],
#        [4, 5],
#        [7, 8]]),
#  array([[3],
#        [6],
#        [9]])]

3. np.hsplit()

hsplit() 沿水平方向(列)分割数组。适用于至少有两列的数组,相当于 np.split(arr, indices_or_sections, axis=1)

示例

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
result = np.hsplit(arr, 2)
print(result)
# 输出:
# [array([[1, 2],
#        [5, 6]]),
#  array([[3, 4],
#        [7, 8]])]

4. np.vsplit()

vsplit() 沿垂直方向(行)分割数组。适用于至少有两行的数组,相当于 np.split(arr, indices_or_sections, axis=0)

示例

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
result = np.vsplit(arr, 2)
print(result)
# 输出:
# [array([[1, 2, 3],
#        [4, 5, 6]]),
#  array([[ 7,  8,  9],
#        [10, 11, 12]])]

5. np.dsplit()

dsplit() 用于分割三维数组的第三维(深度),相当于 np.split(arr, indices_or_sections, axis=2)。适用于三维数组。

示例

arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
result = np.dsplit(arr, 3)
print(result)
# 输出:
# [array([[[ 1],
#         [ 4]],
#
#        [[ 7],
#         [10]]]),
#  array([[[ 2],
#         [ 5]],
#
#        [[ 8],
#         [11]]]),
#  array([[[ 3],
#         [ 6]],
#
#        [[ 9],
#         [12]]])]

6.总结

函数 描述
np.split() 沿指定轴均匀分割数组,不能均分时报错
np.array_split() 沿指定轴分割数组,允许不均匀分割
np.hsplit() 沿水平方向分割数组(仅适用于二维及以上数组)
np.vsplit() 沿垂直方向分割数组(仅适用于二维及以上数组)
np.dsplit() 沿第三维分割三维数组

这些分割方法有助于将数组按不同需求拆分,用于处理和分析大型多维数据。


6.6、总结

变形操作 描述 函数/方法
转置 交换维度 transpose(), T, swapaxes()
翻转 沿指定轴翻转 flip(), flipud(), fliplr()
重塑 改变形状 reshape(), ravel(), flatten()
拼接 连接数组 concatenate(), stack(), vstack(), hstack()
分裂 拆分数组 split(), hsplit(), vsplit()

这些变形操作帮助在数据处理中更灵活地操作数组结构,适应不同计算场景的需求。

7、布尔型数组

布尔型数组是一种只包含布尔值 (TrueFalse) 的数组,常用于筛选、条件判断和数据分析。在 NumPy 中,布尔型数组的创建和操作是非常灵活和高效的。

7.1.创建布尔型数组

在 NumPy 中,可以通过多种方式创建布尔型数组,以下是常用方法:

1.使用条件表达式创建布尔数组

将条件表达式应用于 NumPy 数组,可以返回一个布尔型数组。

import numpy as np

# 示例数组
arr = np.array([1, 2, 3, 4, 5])
# 通过条件表达式生成布尔数组
bool_arr = arr > 3
print(bool_arr)  # 输出: [False False False  True  True]

2.直接创建布尔数组

可以使用 np.array() 来直接创建布尔数组:

bool_arr = np.array([True, False, True])
print(bool_arr)  # 输出: [ True False  True]

3.使用逻辑运算符生成布尔数组

对数组进行逻辑运算(如 &, |, ~)会生成布尔数组。

arr1 = np.array([True, False, True])
arr2 = np.array([False, True, True])
result = arr1 & arr2  # 逻辑与运算
print(result)  # 输出: [False False  True]

4.使用 np.full() 创建指定形状的布尔数组

可以使用 np.full() 创建全 True 或全 False 的布尔数组。

# 创建形状为 (2, 3) 的布尔数组,全为 True
bool_arr = np.full((2, 3), True)
print(bool_arr)
# 输出:
# [[ True  True  True]
#  [ True  True  True]]

语法解释:

np.full(shape, fill_value, dtype=None, order='C')
  • shape:数组的形状,以元组形式指定。如 (2, 3) 表示 2 行 3 列的数组。

  • fill_value:填充数组的值。可以是整数、浮点数或布尔值。

  • dtype(可选):数组的数据类型,默认为 None,即由 fill_value 自动推断。

  • order(可选):数组的存储顺序,‘C’ 表示行优先(C 风格),‘F’ 表示列优先(Fortran 风格)。默认值为 ‘C’。

5.使用 np.ones()np.zeros() 并指定 dtype=bool

也可以通过 np.ones()np.zeros() 创建布尔数组。

# 创建全为 True 的布尔数组
true_arr = np.ones((2, 3), dtype=bool)
print(true_arr)

# 创建全为 False 的布尔数组
false_arr = np.zeros((2, 3), dtype=bool)
print(false_arr)

6.使用 np.random.choice() 随机生成布尔数组

np.random.choice() 可以用来随机生成布尔值。

bool_arr = np.random.choice([True, False], size=(3, 3))
print(bool_arr)

语法解释:

np.random.choice(a, size=None, replace=True, p=None)
  • a:可以是数组或整数。如果是数组,则从中随机选择元素;如果是整数 n,则视为 np.arange(n)
  • size(可选):输出数组的形状。如果为 None,则返回单个随机选择的元素;如果为整数或元组,表示所需的输出形状。
  • replace(可选):是否允许重复选择,默认值为 True(允许重复)。如果设为 False,则为不重复抽样。
  • p(可选):每个元素被选中的概率分布,必须与 a 的长度相同,并且总和为 1。默认情况下,均匀分布(即所有元素被选中的概率相同)。

这些方法提供了灵活的方式来生成布尔型数组,在数据筛选和逻辑判断中非常有用。

7.2布尔数组的常见操作

  1. 计数 Truenp.sum() 可以统计布尔数组中 True 的个数。

    bool_arr = np.array([True, False, True, True])
    count = np.sum(bool_arr)
    print(count)  # 输出: 3
    
  2. 判断全真或全假

  • np.all():如果布尔数组中的所有值都为 True,返回 True,否则返回 False

  • np.any():如果布尔数组中有一个值为 True,返回 True,否则返回 False

    bool_arr = np.array([True, False, True])
    print(np.all(bool_arr))  # 输出: False
    print(np.any(bool_arr))  # 输出: True
    
  1. 反转布尔值~ 运算符可以反转布尔数组中的值。

    bool_arr = np.array([True, False, True])
    print(~bool_arr)  # 输出: [False  True False]
    
  2. 筛选特定条件下的元素

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

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐