超详细的NumPy

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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值