杰瑞科技汇

Python中np.ndarray究竟是什么?

什么是 np.ndarray

np.ndarray (N-dimensional Array) 是 NumPy 库定义的一个多维数组对象,你可以把它理解为一个表格,它可以是一维的(像列表)、二维的(像矩阵),甚至是三维、四维或更高维度的。

Python中np.ndarray究竟是什么?-图1
(图片来源网络,侵删)

与 Python 内置的 list (列表) 相比,np.ndarray 具有以下核心优势,这也是 NumPy 库如此强大的原因:

  1. 性能优越np.ndarray 中的所有元素必须是相同类型的数据(通常是数值类型),并且它们在内存中是连续存储的,这使得 NumPy 能够利用 CPU 的向量化指令进行高效计算,速度远快于 Python 的 list
  2. 丰富的函数库:NumPy 提供了大量的数学函数、线性代数函数、傅里叶变换函数等,可以直接对整个数组进行操作,无需编写循环,这极大地简化了代码并提高了效率。
  3. 广播机制:这是一个非常强大的特性,允许在不同形状的数组之间执行算术运算,NumPy 会自动将较小的数组“扩展”以匹配较大数组的形状,使得代码更简洁、高效。
  4. 便捷的索引和切片np.ndarray 提供了比 Python list 更强大、更灵活的索引和切片功能,可以轻松访问和修改数组的任意部分。

如何创建 np.ndarray

创建 np.ndarray 的方法有很多,这里介绍最常用的几种:

1 从 Python 列表创建

这是最直接的方式,你可以从一维列表、二维列表等创建数组。

import numpy as np
# 从一维列表创建
arr1d = np.array([1, 2, 3, 4, 5])
print("一维数组:")
print(arr1d)
print("类型:", type(arr1d))
print("数据类型:", arr1d.dtype) # 默认会推断数据类型
# 从二维列表创建(类似矩阵)
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("\n二维数组:")
print(arr2d)
print("形状:", arr2d.shape) # (2, 3) 表示2行3列

2 使用 NumPy 内置函数创建

NumPy 提供了专门用于创建特定类型数组的函数,非常方便。

Python中np.ndarray究竟是什么?-图2
(图片来源网络,侵删)
# 创建一个全为0的数组
zeros_arr = np.zeros((3, 4)) # 形状为3行4列
print("全0数组:")
print(zeros_arr)
# 创建一个全为1的数组
ones_arr = np.ones((2, 2), dtype=int) # 可以指定数据类型
print("\n全1数组:")
print(ones_arr)
# 创建一个单位矩阵
identity_matrix = np.eye(3)
print("\n单位矩阵:")
print(identity_matrix)
# 创建一个有固定范围的数组
range_arr = np.arange(10) # 类似 range(10)
print("\narange数组:")
print(range_arr)
# 创建一个有固定间隔的数组
linspace_arr = np.linspace(0, 1, 5) # 从0到1,生成5个等间距的点
print("\nlinspace数组:")
print(linspace_arr)
# 创建一个随机数组
random_arr = np.random.rand(3, 3) # 生成一个3x3的[0, 1)区间的随机浮点数数组
print("\n随机数组:")
print(random_arr)

np.ndarray 的核心属性

了解这些属性是操作数组的基础:

  • ndarray.shape:一个元组,表示数组的维度大小。(2, 3) 表示一个2行3列的二维数组。
  • ndarray.ndim:整数,表示数组的轴(维度)的数量,一维数组的 ndim 是 1,二维数组的 ndim 是 2。
  • ndarray.size:整数,表示数组中元素的总数量,等于 shape 中所有元素的乘积。
  • ndarray.dtype:描述数组元素类型的对象。int32, float64, bool 等。
  • ndarray.itemsize:数组中每个元素所占用的字节数。
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64)
print("数组:\n", arr)
print("形状:", arr.shape)      # 输出: (2, 3)
print("维度:", arr.ndim)       # 输出: 2
print("元素总数:", arr.size)    # 输出: 6
print("数据类型:", arr.dtype)   # 输出: float64
print("每个元素字节数:", arr.itemsize) # 输出: 8 (因为float64占8个字节)

np.ndarray 的核心操作

1 索引和切片

NumPy 的索引和切片语法与 Python 列表非常相似,但功能更强大。

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
# 获取单个元素
print("第一行第二列的元素:", arr[0, 1]) # 输出: 2
# 切片
print("\n第一行:")
print(arr[0, :]) # 或 arr[0]
print("\n第二列:")
print(arr[:, 1])
print("\n获取一个子矩阵 (前两行,后两列):")
print(arr[:2, 2:])

2 整数数组索引

使用一个列表或数组作为索引来选取特定的元素。

arr = np.array([[1, 2], [3, 4], [5, 6]])
print("原始数组:\n", arr)
# 选取第0行和第2行,第1列的元素
# 索引数组 [0, 2] 对应行,索引数组 [1] 对应列
print("\n使用整数数组索引选取的元素:", arr[[0, 2], [1]]) # 输出: [2 6]

3 布尔索引

使用一个布尔数组来筛选元素,非常直观。

Python中np.ndarray究竟是什么?-图3
(图片来源网络,侵删)
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
# 创建一个布尔条件
condition = arr > 4
print("布尔条件:", condition) # 输出: [False False False False  True  True  True  True]
# 使用这个布尔数组进行索引
print("\n大于4的元素:", arr[condition]) # 输出: [5 6 7 8]
# 可以直接在索引中写表达式
print("\n小于等于4的元素:", arr[arr <= 4]) # 输出: [1 2 3 4]

4 数学运算

这是 NumPy 最强大的地方,对数组的运算会作用于每个元素,无需编写循环。

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
# 加法
print("a + b:", a + b) # 输出: [11 22 33 44]
# 减法
print("a - b:", a - b) # 输出: [-9 -18 -27 -36]
# 乘法 (元素级)
print("a * b:", a * b) # 输出: [ 10  40  90 160]
# 除法
print("a / b:", a / b) # 输出: [0.1  0.1  0.1  0.1]
# 与标量的运算
print("a * 2:", a * 2) # 输出: [ 2  4  6  8]
# 平方
print("a ** 2:", a ** 2) # 输出: [ 1  4  9 16]
# 三角函数
print("sin(a):", np.sin(a)) # 输出: [ 0.84147098  0.90929743  0.14112001 -0.7568025 ]

5 广播

当两个形状不同的数组进行运算时,NumPy 会尝试通过“广播”机制使它们兼容。

广播规则

  1. 如果两个数组的维度数不同,在较小的数组前面补 1
  2. 如果两个数组在某个维度上的大小不同,其中一个必须是 1
  3. 如果两个数组在任何维度上的大小都不匹配,且没有一个是 1,则会引发错误。

示例: 将一个一维数组 v 加到二维数组 m 的每一行上。

m = np.array([[1, 2, 3], [4, 5, 6]])
v = np.array([10, 20, 30])
# m 的形状是 (2, 3)
# v 的形状是 (3,)
# 广播过程:
# 1. v 的形状被扩展为 (1, 3) 来匹配 m 的维度数
# 2. v 的形状 (1, 3) 被扩展为 (2, 3) 以匹配 m 的形状
#    NumPy 会将 v 的行复制一份
# 最终效果相当于:
# m + [[10, 20, 30],
#      [10, 20, 30]]
result = m + v
print("m:\n", m)
print("v:\n", v)
print("m + v (广播后):\n", result)
# 输出:
# [[11 22 33]
#  [14 25 36]]

修改 np.ndarray 的形状

  • ndarray.reshape(new_shape):返回一个具有新形状的数组,不修改原始数据,原始数组和返回的数组共享数据。
  • ndarray.resize(new_shape):直接在原始数组上进行修改,改变其形状。
  • ndarray.flatten():将多维数组展平为一维数组,并返回一个副本
arr = np.arange(6)
print("原始数组:", arr) # [0 1 2 3 4 5]
# reshape
reshaped_arr = arr.reshape(2, 3)
print("\nreshape后的数组:\n", reshaped_arr)
print("原始数组是否改变:", arr) # 原始数组不变
# resize
arr.resize(3, 2)
print("\nresize后的数组:\n", arr)
# 注意:resize是原地操作,原始数组已经被改变了
# flatten
arr_2d = np.array([[1, 2], [3, 4]])
flattened_arr = arr_2d.flatten()
print("\n展平后的数组:", flattened_arr)
print("原始二维数组:\n", arr_2d) # 原始数组不变

特性 描述
本质 NumPy 的核心数据结构,一个高效的多维数组。
优势 高性能(连续内存,向量化计算)、功能强大(丰富的数学函数)、语法简洁(广播机制)。
创建 np.array(), np.zeros(), np.ones(), np.arange(), np.linspace() 等。
核心属性 shape (形状), ndim (维度), dtype (数据类型), size (元素总数)。
核心操作 索引/切片arr[0, :])、布尔索引arr[arr > 0])、数学运算arr1 + arr2)、广播(不同形状数组运算)。
修改形状 reshape() (返回视图), resize() (原地修改), flatten() (返回副本)。

掌握 np.ndarray 是使用 Python 进行科学计算、数据分析和机器学习(如使用 Pandas, Scikit-learn, TensorFlow, PyTorch 等)的基石,它将你从低效的 Python 循环中解放出来,让你能专注于算法和逻辑本身。

分享:
扫描分享到社交APP
上一篇
下一篇