第四章 NumPy
本章定位:NumPy 是 Python 科学计算的核心基础库,提供了高效的多维数组对象
ndarray与丰富的数学运算函数,是数据分析、机器学习、信号处理等领域的工具基础。相比 Python 原生列表,NumPy 数组支持向量化运算,运算速度快、内存占用低,是数据方向 Python 学习的必备内容。前置准备:使用前需安装 NumPy 库:
pip install numpy行业惯例导入方式:import numpy as np学习目标:掌握 ndarray 数组的创建、索引、变形与运算,能使用 NumPy 完成基础的数值计算、统计分析与矩阵运算。
1 数组的创建与操作(ndarray)
NumPy 的核心是 ndarray(N-dimensional array)多维数组对象,所有数值运算都围绕数组展开。
1.1 创建数组
1.1.1 从序列创建数组
使用 np.array() 可以将 Python 原生的列表、元组等序列转换为 NumPy 数组,自动推断元素数据类型。
import numpy as np
# 从列表创建一维数组
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1)
# 输出: [1 2 3 4 5]
# 从嵌套列表创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2)
# 输出:
# [[1 2 3]
# [4 5 6]]
# 指定数据类型创建
arr3 = np.array([1, 2, 3], dtype=np.float32)
print(arr3.dtype) # float32提示
np.array() 会自动统一数组内元素的数据类型;若同时存在整数和浮点数,会自动向上转换为浮点型。
1.1.2 快速创建特殊数组
| 函数 | 功能 | 示例 |
|---|---|---|
np.arange(start, end, step) | 生成连续整数序列数组,左闭右开 | np.arange(0, 10, 2) → [0 2 4 6 8] |
np.linspace(start, end, num) | 生成指定个数的均匀间隔数组 | np.linspace(0, 10, 5) → [ 0. 2.5 5. 7.5 10. ] |
np.zeros(shape) | 生成指定形状的全零数组 | np.zeros((2, 3)) → 2行3列全0矩阵 |
np.ones(shape) | 生成指定形状的全一数组 | np.ones((3, 2)) → 3行2列全1矩阵 |
np.eye(n) | 生成 n 阶单位矩阵 | np.eye(3) → 3阶单位矩阵 |
1.2 数组元素索引与访问
1.2.1 一维数组索引
一维数组的索引、切片规则与 Python 列表高度兼容,同时支持整数数组索引(花式索引),可一次性选取多个位置的元素。
arr = np.array([10, 20, 30, 40, 50])
# 基础索引
print(arr[0]) # 10
print(arr[-1]) # 50
# 切片
print(arr[1:4]) # [20 30 40]
# 整数数组索引(花式索引)
index = [0, 2, 4]
print(arr[index]) # [10 30 50]1.2.2 二维数组索引
二维数组索引格式:arr[行索引, 列索引],行与列均支持切片、整数数组索引,全选对应维度用冒号 : 表示。
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 获取单个元素:第0行第1列
print(arr[0, 1]) # 2
# 切片:获取所有行,第1列
print(arr[:, 1]) # [2 5 8]
# 切片:获取第1-2行,第0-1列
print(arr[1:3, 0:2])
# [[4 5]
# [7 8]]
# 布尔索引:筛选大于5的元素
print(arr[arr > 5]) # [6 7 8 9]1.2.3 笛卡尔积索引 np.ix_()
np.ix_() 可以实现多维度索引的笛卡尔积组合,一次性获取多个交叉位置的元素。
arr = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
# 获取 (0,1)、(0,3)、(-1,1)、(-1,3) 四个位置的元素
print(arr[np.ix_([0, -1], [1, 3])])
# [[ 2 4]
# [10 12]]1.3 数组核心属性
| 属性 | 说明 | 示例结果 |
|---|---|---|
ndim | 数组的维度数(轴数) | 二维数组 → 2 |
shape | 数组的形状,格式为 (行数, 列数) | 2行3列 → (2, 3) |
dtype | 数组元素的数据类型 | 整数数组 → int64 |
size | 数组元素总个数 | 2行3列 → 6 |
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.ndim) # 2
print(arr.shape) # (2, 3)
print(arr.dtype) # int64
print(arr.size) # 61.4 数组形状处理
1.4.1 reshape:重塑形状(返回副本)
reshape() 可以改变数组的形状,返回新数组副本,不修改原数组。参数 -1 表示自动计算该维度的大小。
arr = np.arange(6) # [0 1 2 3 4 5]
# 重塑为 2行3列
arr2 = arr.reshape(2, 3)
print(arr2)
# [[0 1 2]
# [3 4 5]]
# -1 自动计算维度
arr3 = arr.reshape(3, -1)
print(arr3.shape) # (3, 2)1.4.2 resize:重塑形状(修改原数组)
resize() 功能与 reshape 类似,但直接修改原数组本身(视图),无返回值。
arr = np.arange(6)
arr.resize(2, 3)
print(arr)
# [[0 1 2]
# [3 4 5]]1.4.3 ravel:多维展平为一维(返回视图)
ravel() 将多维数组展平为一维数组,返回原数组的视图,修改新数组会影响原数组。默认按行(C顺序)展平,order='F' 按列展平。
arr = np.array([[1, 2], [3, 4]])
print(arr.ravel()) # [1 2 3 4]
# 按列展平
print(arr.ravel(order='F')) # [1 3 2 4]1.4.4 flatten:多维展平为一维(返回副本)
flatten() 功能与 ravel 一致,但返回原数组的副本,修改新数组不会影响原数组。
arr = np.array([[1, 2], [3, 4]])
arr_flat = arr.flatten()
arr_flat[0] = 100
print(arr) # 原数组不变
# [[1 2]
# [3 4]]补充:数组转置
二维数组可直接通过 .T 属性获取转置数组:
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.T)
# [[1 4]
# [2 5]
# [3 6]]1.5 数组的堆叠与拼接
将多个数组合并为一个数组,分为纵向堆叠和横向堆叠两种方向。
| 函数 | 作用 | 规则 |
|---|---|---|
np.row_stack() / np.vstack() | 纵向(垂直方向)堆叠 | 所有数组的列数必须相同 |
np.column_stack() / np.hstack() | 横向(水平方向)拼接 | 所有数组的行数必须相同 |
np.concatenate(arr_list, axis=0) | 按指定轴拼接 | axis=0纵向,axis=1横向 |
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
# 纵向堆叠
print(np.vstack([arr1, arr2]))
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
# 横向拼接
print(np.hstack([arr1, arr2]))
# [[1 2 5 6]
# [3 4 7 8]]
# 通用拼接函数,axis=1 横向
print(np.concatenate([arr1, arr2], axis=1))2 数组的基本运算
NumPy 数组支持向量化运算,无需循环即可对所有元素批量执行运算,代码简洁且效率远高于原生列表循环。
2.1 算术运算
支持 + - * / % // ** 等运算符,逐元素对应运算。
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
print(arr1 + arr2) # [5 7 9]
print(arr1 * 2) # [2 4 6] 标量广播
print(arr1 ** 2) # [1 4 9]广播机制
当运算双方形状不同时,NumPy 会自动触发广播机制,将维度少的数组自动扩展匹配维度。例如标量与数组运算、一维数组与二维数组运算,只要维度兼容即可自动广播。
2.2 比较运算
支持 > >= < <= == != 比较运算符,返回相同形状的布尔数组。
arr = np.array([1, 3, 5, 7, 9])
# 比较运算,返回布尔数组
print(arr > 5) # [False False False True True]
# 布尔索引:筛选满足条件的元素
print(arr[arr > 5]) # [7 9]3 常用数学与统计函数
NumPy 提供了丰富的统计函数,支持按指定轴(axis)计算。
axis 参数说明:
axis=0:按**垂直方向(列方向)**计算,跨行运算axis=1:按**水平方向(行方向)**计算,跨列运算- 不指定 axis 时,对整个数组所有元素计算
| 函数 | 功能 |
|---|---|
np.sum(arr, axis=None) | 求和 |
np.mean(arr, axis=None) | 求算术平均值 |
np.std(arr, axis=None) | 求标准差 |
np.var(arr, axis=None) | 求方差 |
np.min(arr, axis=None) | 求最小值 |
np.max(arr, axis=None) | 求最大值 |
np.argmin(arr, axis=None) | 求最小值的索引 |
np.argmax(arr, axis=None) | 求最大值的索引 |
arr = np.array([[1, 2, 3],
[4, 5, 6]])
# 整个数组求和
print(np.sum(arr)) # 21
# 按列求和(axis=0)
print(np.sum(arr, axis=0)) # [5 7 9]
# 按行求均值(axis=1)
print(np.mean(arr, axis=1)) # [2. 5.]4 线性代数基础运算
NumPy 提供了基础的线性代数运算能力,满足基础矩阵计算需求。
4.1 特殊矩阵
| 函数 | 功能 |
|---|---|
np.zeros((m,n)) | m行n列全零矩阵 |
np.ones((m,n)) | m行n列全一矩阵 |
np.eye(n) | n阶单位矩阵(对角线为1,其余为0) |
np.diag(列表) | 根据列表生成对角矩阵;传入二维数组则提取对角线元素 |
# 3阶单位矩阵
print(np.eye(3))
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
# 提取矩阵对角线
arr = np.array([[1,2],[3,4]])
print(np.diag(arr)) # [1 4]4.2 矩阵运算
| 函数/运算符 | 功能 | 注意事项 |
|---|---|---|
np.dot(arr1, arr2) / arr1 @ arr2 | 矩阵点积/乘法 | 第一个数组的列数 = 第二个数组的行数 |
np.linalg.eig(arr) | 计算矩阵的特征值与特征向量 | 返回(特征值数组, 特征向量数组) |
np.linalg.solve(A, b) | 求解多元线性方程组 Ax = b | A为系数矩阵,b为常数项向量 |
# 矩阵乘法
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(np.dot(A, B))
# [[19 22]
# [43 50]]5 伪随机数生成
numpy.random 子模块提供了丰富的伪随机数生成功能,支持多种分布的随机数生成。
5.1 常用随机函数
| 函数 | 功能 | 示例 |
|---|---|---|
np.random.rand(shape) | 生成[0, 1)均匀分布随机浮点数 | np.random.rand(2,3) → 2行3列随机数 |
np.random.randint(low, high, size) | 生成[low, high)随机整数 | np.random.randint(0, 10, size=5) → 5个0-9随机整数 |
np.random.randn(shape) | 生成标准正态分布随机数(均值0,方差1) | np.random.randn(10) → 10个标准正态分布数 |
np.random.normal(loc, scale, size) | 生成指定均值、标准差的正态分布 | np.random.normal(100, 10, size=100) |
5.2 随机种子
使用 np.random.seed(种子值) 可以固定随机数生成器的状态,保证每次运行生成的随机数一致,便于结果复现与调试。
np.random.seed(42)
print(np.random.randint(0, 10, 5))
# 固定种子后,每次运行结果都为 [6 3 7 4 6]本章练习
基础题
- 创建一个 3 行 4 列的全零数组,将第 1 行第 2 列元素修改为 10,输出数组与它的
shape、dtype、size。 - 使用
np.arange生成 0~20 的整数数组,重塑为 4 行 5 列,计算所有元素的和、均值、标准差。 - 创建两个 2 行 3 列的随机整数数组(0~10),分别进行纵向堆叠与横向拼接,输出结果。
- 生成 100 个均值为 80、标准差为 10 的正态分布随机数,计算其中大于 90 的元素个数。
进阶题
- 创建一个 5×5 的随机整数矩阵(10~99),提取它的主对角线元素,计算对角线元素的和。
- 求解二元一次方程组:$\begin{cases}2x + y = 7 \ x - 3y = -2 \end{cases}$,使用
np.linalg.solve实现。 - 生成 1000 个 0~100 的随机整数,统计每个数字出现的次数。
本章常见易错点
- 索引越界:数组索引从 0 开始,最大索引为
长度-1,超出范围会触发IndexError。 - 形状不匹配:数组运算、堆叠时,对应维度长度不匹配会触发报错,堆叠前需确认维度。
- reshape 与 resize 混淆:
reshape返回副本不修改原数组,resize直接修改原数组,注意区分使用场景。 - 视图与副本混淆:
ravel返回视图,修改会影响原数组;flatten返回副本,互不影响,避免误用导致数据意外修改。 - axis 参数搞反:
axis=0是按列(纵向)计算,axis=1是按行(横向)计算,注意不要混淆方向。