1. 什么是 NumPy? #
NumPy(Numerical Python)是 Python 中最基础的数值计算库。它提供了高性能的多维数组对象(ndarray)以及丰富的数学函数。几乎所有的数据科学、机器学习、科学计算库都基于 NumPy。
为什么要用 NumPy?
想象一下,如果你想计算一个包含 100 万个数字的列表的每个元素的平方。使用 Python 的普通列表需要逐个处理,非常慢。但使用 NumPy 数组,一行代码就能完成,速度可以提升几十倍甚至上百倍。
NumPy 的优势:
- 速度快:使用 C 语言实现,比 Python 原生列表快得多
- 向量化计算:可以对整个数组进行数学运算,无需循环
- 内存高效:存储相同的数据,NumPy 数组比 Python 列表占用更少内存
- 丰富的功能:提供大量的数学、统计、线性代数函数
- 生态基础:Pandas、Matplotlib、Scikit-learn 等都依赖 NumPy
前置知识补充:
- 数组:数组是一个包含多个元素的数据结构,元素通常是同类型的(比如都是整数或都是浮点数)。一维数组就像一行数字,二维数组像表格,三维数组像立方体。
- 向量:一维数组可以称为向量,比如
[1, 2, 3]。- 矩阵:二维数组可以称为矩阵,比如
[[1, 2], [3, 4]]。- 向量化计算:对数组中的每个元素同时执行相同的操作,比如对数组
[1, 2, 3]的每个元素加 1,得到[2, 3, 4]。
2. 环境准备 #
在学习 NumPy 之前,需要确保你的 Python 环境已经准备好。NumPy 支持 Python 3.8 及以上版本。
2.1 检查 Python 版本 #
在安装之前,先检查一下你的 Python 版本是否符合要求。
# Windows PowerShell:查看 Python 版本
python --version# macOS 终端:查看 Python 版本
python3 --version2.2 安装 NumPy #
NumPy 可以直接通过 pip 安装。安装过程会自动下载所需的依赖包。
# 说明:Windows PowerShell 安装 NumPy
# 先升级 pip 到最新版本,确保能正常安装依赖
python -m pip install --upgrade pip
# 安装 NumPy 库
python -m pip install numpy# 说明:macOS / Linux 终端安装 NumPy
# 先升级 pip 到最新版本
python3 -m pip install --upgrade pip
# 安装 NumPy 库
python3 -m pip install numpy网络加速提示:如果从 PyPI 下载较慢,可以使用国内镜像:
- Windows:
python -m pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple- macOS:
python3 -m pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
安装问题提示:在某些旧环境中可能遇到二进制轮子缺失的问题,可以尝试:
- Windows:
python -m pip install numpy --prefer-binary- macOS:
python3 -m pip install numpy --prefer-binary或者直接安装 Anaconda/Miniconda,它们自带 NumPy。
2.3 验证安装 #
安装完成后,验证一下是否安装成功。
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.array() |
将 Python 列表转换为 NumPy 数组 | object:要转换的列表或可迭代对象 |
ndarray 数组对象 |
ndarray 属性 |
数组的各种属性(如 shape、dtype 等) | 无 | 对应属性值 |
# -*- coding: utf-8 -*-
# 说明:验证 NumPy 是否安装成功
# 说明:导入 NumPy 库
# 通常使用 np 作为 NumPy 的别名,这是约定俗成的做法
import numpy as np
# 说明:创建一个简单的数组进行测试
# array() 函数可以将 Python 列表转换为 NumPy 数组
test_array = np.array([1, 2, 3, 4, 5])
# 说明:打印数组,验证安装是否成功
print("安装成功!测试数组:", test_array)
# 说明:打印 NumPy 版本信息
print(f"NumPy 版本:{np.__version__}")
# 说明:如果没有报错并输出了数组,说明安装成功3. 核心概念 #
在使用 NumPy 之前,需要理解几个核心概念。这些概念是理解 NumPy 的基础。
3.1 ndarray(数组对象) #
ndarray 是 NumPy 的核心,它是一个多维数组对象。所有元素必须是相同类型(比如都是整数或都是浮点数)。
3.2 维度(Dimensions) #
- 0 维:标量(单个数字),如
42 - 1 维:向量(一行数字),如
[1, 2, 3] - 2 维:矩阵(表格),如
[[1, 2], [3, 4]] - 3 维及以上:多维数组
3.3 形状(Shape) #
形状描述数组在每个维度上的大小。例如:
[1, 2, 3]的形状是(3,),表示有 3 个元素[[1, 2], [3, 4]]的形状是(2, 2),表示有 2 行 2 列
3.4 数据类型(dtype) #
NumPy 数组中的元素必须是相同类型,比如:
int32:32 位整数float64:64 位浮点数(小数)bool:布尔值(True/False)
4. 创建数组 #
NumPy 提供了多种创建数组的方法,从 Python 列表转换是最常用的方式。
4.1 从 Python 列表创建 #
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.array() |
将 Python 列表转换为 NumPy 数组 | object:要转换的列表或可迭代对象 |
ndarray 数组对象 |
.shape |
获取数组的形状(每个维度的大小) | 无(属性) | 元组,表示数组形状 |
# -*- coding: utf-8 -*-
# 说明:演示如何从 Python 列表创建 NumPy 数组
# 说明:导入 NumPy 库
import numpy as np
# 说明:从 Python 列表创建一维数组
# array() 函数将 Python 列表转换为 NumPy 数组
arr1 = np.array([1, 2, 3, 4, 5])
print("一维数组:", arr1)
# 说明:创建二维数组(矩阵形式)
# 传入一个嵌套列表,外层列表的每个元素是一行
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print("二维数组(2行3列):")
print(arr2)
# 说明:创建三维数组(较少使用,但了解即可)
# 三层嵌套列表
arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("三维数组:")
print(arr3)
print(f"形状:{arr3.shape}") # 形状是 (2, 2, 2)4.2 创建特殊数组 #
NumPy 提供了许多函数来创建常用的特殊数组。
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.zeros() |
创建全零数组 | shape:数组形状,如 (2, 3) |
全零数组 |
np.ones() |
创建全一数组 | shape:数组形状,如 (3, 2) |
全一数组 |
np.eye() |
创建单位矩阵(对角线为1,其他为0) | N:矩阵大小 |
单位矩阵 |
np.arange() |
创建等差数列 | start:起始值,stop:结束值(不包含),step:步长 |
等差数列 |
np.linspace() |
创建等间隔数组 | start:起始值,stop:结束值(包含),num:元素个数 |
等间隔数组 |
np.empty() |
创建空数组(值未初始化) | shape:数组形状 |
空数组(值随机) |
# -*- coding: utf-8 -*-
# 说明:演示如何创建特殊的数组
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建全零数组
# zeros() 函数创建一个全为 0 的数组
# 参数 (2, 3) 表示创建一个 2 行 3 列的数组
zeros = np.zeros((2, 3))
print("全零数组(2行3列):")
print(zeros)
# 说明:创建全一数组
# ones() 函数创建一个全为 1 的数组
# 参数 (3, 2) 表示创建一个 3 行 2 列的数组
ones = np.ones((3, 2))
print("\n全一数组(3行2列):")
print(ones)
# 说明:创建单位矩阵(对角线为 1,其他为 0)
# eye() 函数创建单位矩阵
# 参数 3 表示创建一个 3x3 的单位矩阵
identity = np.eye(3)
print("\n单位矩阵(3x3):")
print(identity)
# 说明:创建等差数列
# arange() 函数创建一个等差数列
# 参数:起始值、结束值(不包含)、步长
# 这里从 0 开始,到 10(不包含),步长为 2
range_arr = np.arange(0, 10, 2)
print("\n等差数列(0到10,步长2):", range_arr)
# 说明:创建等间隔数组
# linspace() 函数创建一个等间隔的数组
# 参数:起始值、结束值(包含)、元素个数
# 这里从 0 到 1(包含),创建 5 个等间隔的数
linspace_arr = np.linspace(0, 1, 5)
print("\n等间隔数组(0到1,5个数):", linspace_arr)
# 说明:创建空数组(未初始化,值是随机的)
# empty() 函数创建一个空数组(不初始化值,速度更快)
# 参数 (2, 3) 表示创建一个 2 行 3 列的数组
empty = np.empty((2, 3))
print("\n空数组(值未初始化):")
print(empty)4.3 查看数组属性 #
了解数组的属性有助于更好地使用 NumPy。
本代码块中使用的 NumPy 属性:
| 属性 | 功能说明 | 返回值 |
|---|---|---|
.ndim |
数组的维度数 | 整数(如 1 表示一维,2 表示二维) |
.shape |
数组的形状(每个维度的大小) | 元组(如 (2, 3) 表示 2 行 3 列) |
.size |
数组中元素的总数 | 整数 |
.dtype |
数组元素的数据类型 | 数据类型(如 int64、float64) |
.itemsize |
每个元素占用的字节数 | 整数(字节数) |
.nbytes |
数组占用的总字节数 | 整数(总字节数 = size × itemsize) |
# -*- coding: utf-8 -*-
# 说明:演示如何查看数组的属性
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个示例数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 说明:查看数组的维度(维度数)
# ndim 属性返回数组的维度数
print("维度数:", arr.ndim) # 2 维
# 说明:查看数组的形状(每个维度的大小)
# shape 属性返回一个元组,表示数组的形状
print("形状:", arr.shape) # (2, 3) 表示 2 行 3 列
# 说明:查看数组的元素总数
# size 属性返回数组中元素的总数
print("元素总数:", arr.size) # 2 * 3 = 6
# 说明:查看数组的数据类型
# dtype 属性返回数组中元素的数据类型
print("数据类型:", arr.dtype) # int64(整数)
# 说明:查看数组的大小(字节数)
# itemsize 属性返回每个元素占用的字节数
print("每个元素的字节数:", arr.itemsize) # 8 字节(int64)
# 说明:查看数组的总字节数
# nbytes 属性返回数组占用的总字节数
print("总字节数:", arr.nbytes) # 6 * 8 = 48 字节5. 索引与切片 #
索引和切片是访问和修改数组元素的重要方式。NumPy 的索引方式与 Python 列表类似,但支持多维索引。
5.1 基本索引 #
| 方法/操作 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.arange() |
创建等差数列 | start:起始值,stop:结束值(不包含) |
等差数列 |
.reshape() |
改变数组形状 | shape:新形状,如 (3, 3) |
重塑后的数组(视图) |
arr[i, j] |
访问数组中的单个元素 | i:行索引,j:列索引 |
单个元素值 |
arr[i] |
访问数组的第 i 行 | i:行索引 |
第 i 行的数组 |
arr[:, j] |
访问数组的第 j 列 | j:列索引 |
第 j 列的数组 |
# -*- coding: utf-8 -*-
# 说明:演示基本的索引操作
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个 3x3 的数组作为示例
# arange(1, 10) 创建 [1, 2, 3, 4, 5, 6, 7, 8, 9]
# reshape(3, 3) 将其重塑为 3 行 3 列
arr = np.arange(1, 10).reshape(3, 3)
print("原始数组:")
print(arr)
# 说明:访问单个元素
# 使用 [行索引, 列索引] 的方式访问
# 索引从 0 开始,第一个元素的索引是 0
element = arr[1, 1] # 访问第 2 行第 2 列的元素
print(f"\n第2行第2列的元素:{element}")
# 说明:访问整行
# 只指定行索引,不指定列索引,返回整行
row = arr[0] # 访问第 1 行
print(f"第1行:{row}")
# 说明:访问整列
# 使用 [:, 列索引] 的方式访问整列
# : 表示所有行
col = arr[:, 0] # 访问第 1 列
print(f"第1列:{col}")5.2 切片操作 #
切片可以获取数组的子集。
| 方法/操作 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
arr[start:end, start:end] |
切片获取子数组 | start:起始索引,end:结束索引(不包含) |
子数组 |
arr[-1] |
使用负数索引(从末尾开始) | -1 表示最后一个元素 |
最后一个元素或行 |
arr[:, :] |
获取所有行和所有列 | 无 | 完整的数组 |
# -*- coding: utf-8 -*-
# 说明:演示切片操作
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个 3x3 的数组
arr = np.arange(1, 10).reshape(3, 3)
print("原始数组:")
print(arr)
# 说明:切片获取子数组
# 语法:arr[行起始:行结束, 列起始:列结束]
# 注意:结束索引不包含在结果中
# arr[0:2, 1:3] 表示第 1-2 行(索引 0-1),第 2-3 列(索引 1-2)
sub_arr = arr[0:2, 1:3]
print("\n子数组(第1-2行,第2-3列):")
print(sub_arr)
# 说明:使用负数索引(从末尾开始)
# -1 表示最后一个元素,-2 表示倒数第二个
last_row = arr[-1] # 最后一行
print(f"\n最后一行:{last_row}")
# 说明:省略所有索引(获取所有行/列)
all_rows = arr[:, :] # 获取所有行和所有列(等同于 arr)
print(f"\n所有行:")
print(all_rows)5.3 布尔索引 #
布尔索引可以根据条件筛选数组元素。
| 方法/操作 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
arr > value |
比较运算,返回布尔数组 | value:比较值 |
布尔数组(True/False) |
arr[mask] |
使用布尔掩码筛选元素 | mask:布尔数组 |
满足条件的元素数组 |
(条件1) & (条件2) |
组合多个条件(且) | 两个布尔条件 | 组合后的布尔数组 |
arr[condition] = value |
根据条件修改元素 | condition:布尔条件,value:新值 |
无(修改原数组) |
# -*- coding: utf-8 -*-
# 说明:演示布尔索引(根据条件筛选元素)
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个示例数组
arr = np.arange(1, 10).reshape(3, 3)
print("原始数组:")
print(arr)
# 说明:创建布尔掩码(条件)
# 比较运算返回一个布尔数组,其中 True 表示满足条件,False 表示不满足
mask = arr > 5
print("\n布尔掩码(大于5的元素为True):")
print(mask)
# 说明:使用布尔掩码筛选元素
# 只返回掩码中为 True 的位置对应的元素
filtered = arr[mask]
print("\n满足条件(大于5)的元素:", filtered)
# 说明:更复杂的条件
# 可以使用 &(且)、|(或)、~(非)组合多个条件
# 注意:必须使用括号
condition = (arr > 3) & (arr < 7)
result = arr[condition]
print("\n大于3且小于7的元素:", result)
# 说明:修改满足条件的元素
arr[arr > 5] = 0 # 将所有大于 5 的元素设置为 0
print("\n修改后(大于5的元素变为0):")
print(arr)5.4 花式索引 #
花式索引可以根据索引列表选择元素。
| 方法/操作 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
arr[rows] |
使用索引列表选择行 | rows:行索引列表 |
选中的行数组 |
arr[rows, cols] |
使用索引列表选择元素 | rows:行索引列表,cols:列索引列表 |
选中的元素数组 |
np.ix_() |
创建索引网格(用于矩形区域选择) | rows:行索引列表,cols:列索引列表 |
索引网格元组 |
# -*- coding: utf-8 -*-
# 说明:演示花式索引(使用索引列表选择元素)
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个示例数组
arr = np.arange(1, 10).reshape(3, 3)
print("原始数组:")
print(arr)
# 说明:使用索引列表选择特定行
# [0, 2] 表示选择第 1 行和第 3 行(索引 0 和 2)
rows = [0, 2]
selected_rows = arr[rows]
print("\n选择的第1行和第3行:")
print(selected_rows)
# 说明:使用索引列表选择特定元素
# 同时指定行索引和列索引
rows = [0, 2] # 选择第 1 行和第 3 行
cols = [2, 0] # 分别选择第 3 列和第 1 列
selected = arr[rows, cols] # 选择 (0,2) 和 (2,0) 位置的元素
print("\n花式索引结果((0,2) 和 (2,0)):", selected)
# 说明:选择矩形区域
# 使用 np.ix_() 函数创建索引网格
rows = [0, 2]
cols = [0, 2]
grid = arr[np.ix_(rows, cols)] # 选择 (0,0), (0,2), (2,0), (2,2)
print("\n使用 np.ix_() 选择的矩形区域:")
print(grid)6. 数组操作 #
数组操作包括形状改变、拼接、拆分等,这些是数据预处理中常用的操作。
6.1 改变数组形状 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
.reshape() |
改变数组形状(返回视图) | shape:新形状,如 (3, 4) |
重塑后的数组 |
.flatten() |
展平数组(返回副本) | 无 | 一维数组(副本) |
.ravel() |
展平数组(返回视图) | 无 | 一维数组(通常是视图) |
arr[:, None] |
增加维度(将行向量变为列向量) | None:在指定位置添加新维度 |
增加维度后的数组 |
# -*- coding: utf-8 -*-
# 说明:演示如何改变数组的形状
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一维数组
vector = np.arange(12)
print("原始一维数组:", vector)
print(f"形状:{vector.shape}")
# 说明:重塑为二维数组
# reshape() 方法改变数组的形状
# 参数 (3, 4) 表示重塑为 3 行 4 列
# 注意:新形状的元素总数必须与原数组相同(12 = 3 * 4)
matrix = vector.reshape(3, 4)
print("\n重塑为 3x4 矩阵:")
print(matrix)
print(f"形状:{matrix.shape}")
# 说明:展平数组(变回一维)
# flatten() 方法返回一个展平后的副本(不影响原数组)
flat1 = matrix.flatten()
print("\nflatten() 展平(返回副本):", flat1)
# 说明:ravel() 方法也可以展平(通常返回视图,可能影响原数组)
flat2 = matrix.ravel()
print("ravel() 展平(可能返回视图):", flat2)
# 说明:改变数组的维度数
# 使用 None 或 np.newaxis 增加维度
row_vec = np.array([1, 2, 3])
col_vec = row_vec[:, None] # 变为列向量(2 维)
print(f"\n原数组:{row_vec}, 形状:{row_vec.shape}")
print(f"列向量:\n{col_vec}, 形状:{col_vec.shape}")6.2 拼接数组 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.vstack() |
垂直拼接(按行拼接,行数增加) | tup:要拼接的数组元组或列表 |
垂直拼接后的数组 |
np.hstack() |
水平拼接(按列拼接,列数增加) | tup:要拼接的数组元组或列表 |
水平拼接后的数组 |
np.concatenate() |
通用拼接函数 | arrays:要拼接的数组列表,axis:拼接的轴(0=行,1=列) |
拼接后的数组 |
# -*- coding: utf-8 -*-
# 说明:演示如何拼接数组
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建两个示例数组
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
print("数组 a:")
print(a)
print("\n数组 b:")
print(b)
# 说明:垂直拼接(按行拼接)
# vstack() 函数将数组垂直堆叠
# 结果的行数增加
vertical = np.vstack([a, b])
print("\n垂直拼接(按行):")
print(vertical)
# 说明:水平拼接(按列拼接)
# hstack() 函数将数组水平堆叠
# 结果的列数增加
horizontal = np.hstack([a, b])
print("\n水平拼接(按列):")
print(horizontal)
# 说明:通用拼接函数
# concatenate() 函数可以指定拼接的轴(axis)
# axis=0 表示按行拼接(垂直),axis=1 表示按列拼接(水平)
concatenated = np.concatenate([a, b], axis=0)
print("\n使用 concatenate() 垂直拼接:")
print(concatenated)6.3 拆分数组 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.hsplit() |
水平拆分(按列拆分) | ary:要拆分的数组,indices:拆分点或部分数 |
拆分后的数组列表 |
np.vsplit() |
垂直拆分(按行拆分) | ary:要拆分的数组,indices:拆分点或部分数 |
拆分后的数组列表 |
np.split() |
通用拆分函数 | ary:要拆分的数组,indices_or_sections:拆分点,axis:拆分的轴 |
拆分后的数组列表 |
# -*- coding: utf-8 -*-
# 说明:演示如何拆分数组
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个示例数组
arr = np.arange(12).reshape(3, 4)
print("原始数组:")
print(arr)
# 说明:水平拆分(按列拆分)
# hsplit() 函数将数组水平拆分成多个子数组
# 参数 2 表示拆分成 2 个部分
parts = np.hsplit(arr, 2)
print("\n水平拆分成 2 部分:")
for i, part in enumerate(parts):
print(f"第 {i+1} 部分:")
print(part)
# 说明:垂直拆分(按行拆分)
# vsplit() 函数将数组垂直拆分成多个子数组
parts = np.vsplit(arr, 3)
print("\n垂直拆分成 3 部分:")
for i, part in enumerate(parts):
print(f"第 {i+1} 部分:")
print(part)
# 说明:通用拆分函数
# split() 函数可以指定拆分的轴
parts = np.split(arr, 3, axis=0) # 按行拆分
print("\n使用 split() 按行拆分:")
for i, part in enumerate(parts):
print(f"第 {i+1} 部分:")
print(part)7. 数学运算 #
NumPy 提供了丰富的数学运算函数,支持向量化计算(对整个数组进行计算)。
7.1 基本运算 #
本代码块中使用的 NumPy 操作:
| 操作 | 功能说明 | 示例 | 返回值 |
|---|---|---|---|
arr1 + arr2 |
向量化加法(对应元素相加) | a + b |
相加后的数组 |
arr1 - arr2 |
向量化减法(对应元素相减) | b - a |
相减后的数组 |
arr1 * arr2 |
向量化乘法(对应元素相乘,不是矩阵乘法) | a * b |
相乘后的数组 |
arr1 / arr2 |
向量化除法(对应元素相除) | b / a |
相除后的数组 |
arr ** n |
幂运算(每个元素的 n 次方) | a ** 2 |
幂运算后的数组 |
arr + scalar |
标量与数组运算(广播) | a + 10 |
每个元素都加上标量的数组 |
arr * scalar |
标量与数组运算(广播) | a * 2 |
每个元素都乘以标量的数组 |
# -*- coding: utf-8 -*-
# 说明:演示基本的数学运算
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建两个示例数组
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
print("数组 a:", a)
print("数组 b:", b)
# 说明:向量化加法(对应元素相加)
# NumPy 可以直接对数组进行数学运算,不需要循环
add_result = a + b
print("\n加法(a + b):", add_result)
# 说明:向量化减法
sub_result = b - a
print("减法(b - a):", sub_result)
# 说明:向量化乘法(对应元素相乘,不是矩阵乘法)
mult_result = a * b
print("乘法(a * b,对应元素相乘):", mult_result)
# 说明:向量化除法
div_result = b / a
print("除法(b / a):", div_result)
# 说明:幂运算
power_result = a ** 2
print("幂运算(a 的平方):", power_result)
# 说明:标量与数组的运算(广播)
# NumPy 会自动将标量广播到数组的每个元素
scalar_add = a + 10
print("\n标量加法(a + 10):", scalar_add)
scalar_mult = a * 2
print("标量乘法(a * 2):", scalar_mult)7.2 数学函数 #
NumPy 提供了丰富的数学函数。
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.sin() |
计算正弦值 | x:角度(弧度) |
正弦值数组 |
np.cos() |
计算余弦值 | x:角度(弧度) |
余弦值数组 |
np.tan() |
计算正切值 | x:角度(弧度) |
正切值数组 |
np.exp() |
计算 e 的 x 次方 | x:指数 |
e^x 数组 |
np.log() |
计算自然对数(以 e 为底) | x:真数 |
自然对数数组 |
np.log10() |
计算以 10 为底的对数 | x:真数 |
常用对数数组 |
np.sqrt() |
计算平方根 | x:被开方数 |
平方根数组 |
np.cbrt() |
计算立方根 | x:被开方数 |
立方根数组 |
np.abs() |
计算绝对值 | x:数值 |
绝对值数组 |
np.floor() |
向下取整 | x:浮点数 |
向下取整后的数组 |
np.ceil() |
向上取整 | x:浮点数 |
向上取整后的数组 |
np.round() |
四舍五入 | x:浮点数 |
四舍五入后的数组 |
np.pi |
圆周率常量 | 无(常量) | 3.14159... |
# -*- coding: utf-8 -*-
# 说明:演示 NumPy 的数学函数
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建示例数组
arr = np.array([1, 2, 3, 4])
# 说明:三角函数
angles = np.array([0, np.pi/4, np.pi/2])
print("角度(弧度):", angles)
print("sin值:", np.sin(angles))
print("cos值:", np.cos(angles))
print("tan值:", np.tan(angles))
# 说明:指数和对数
print("\n指数运算(e的x次方):", np.exp(arr))
print("自然对数:", np.log(arr))
print("以10为底的对数:", np.log10(arr))
# 说明:开方和幂
print("\n平方根:", np.sqrt(arr))
print("立方根:", np.cbrt(arr))
# 说明:绝对值
neg_arr = np.array([-1, -2, 3, -4])
print("\n绝对值:", np.abs(neg_arr))
# 说明:向上取整和向下取整
float_arr = np.array([1.2, 2.7, 3.5, 4.1])
print("\n向下取整:", np.floor(float_arr))
print("向上取整:", np.ceil(float_arr))
print("四舍五入:", np.round(float_arr))8. 统计函数 #
NumPy 提供了丰富的统计函数,可以计算均值、标准差、最大值、最小值等。
8.1 基本统计 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.sum() |
计算所有元素的总和 | a:数组,axis:统计的轴(可选) |
总和值 |
np.mean() |
计算所有元素的平均值 | a:数组,axis:统计的轴(可选) |
平均值 |
np.std() |
计算标准差(衡量数据离散程度) | a:数组,axis:统计的轴(可选) |
标准差 |
np.var() |
计算方差(标准差的平方) | a:数组,axis:统计的轴(可选) |
方差 |
np.max() |
找出最大值 | a:数组,axis:统计的轴(可选) |
最大值 |
np.min() |
找出最小值 | a:数组,axis:统计的轴(可选) |
最小值 |
np.argmax() |
找出最大值的索引 | a:数组,axis:统计的轴(可选) |
最大值的索引 |
np.argmin() |
找出最小值的索引 | a:数组,axis:统计的轴(可选) |
最小值的索引 |
# -*- coding: utf-8 -*-
# 说明:演示 NumPy 的统计函数
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个示例矩阵
matrix = np.arange(1, 10).reshape(3, 3)
print("示例矩阵:")
print(matrix)
# 说明:计算总和
# sum() 函数计算所有元素的总和
total = np.sum(matrix)
print(f"\n总和:{total}")
# 说明:计算均值
# mean() 函数计算所有元素的平均值
average = np.mean(matrix)
print(f"均值:{average:.2f}")
# 说明:计算标准差
# std() 函数计算标准差(衡量数据的离散程度)
std_dev = np.std(matrix)
print(f"标准差:{std_dev:.2f}")
# 说明:计算方差
# var() 函数计算方差(标准差的平方)
variance = np.var(matrix)
print(f"方差:{variance:.2f}")
# 说明:找出最大值和最小值
max_value = np.max(matrix)
min_value = np.min(matrix)
print(f"\n最大值:{max_value}")
print(f"最小值:{min_value}")
# 说明:找出最大值和最小值的索引
max_index = np.argmax(matrix)
min_index = np.argmin(matrix)
print(f"最大值的索引(展平后):{max_index}")
print(f"最小值的索引(展平后):{min_index}")8.2 按轴统计 #
在多维数组中,可以指定统计的轴(维度)。
| 方法 | 功能说明 | 参数说明 | 返回值 |
|---|---|---|---|
np.mean(axis=0) |
沿行方向统计(计算每列的均值) | axis=0:沿行方向 |
每列均值的数组 |
np.mean(axis=1) |
沿列方向统计(计算每行的均值) | axis=1:沿列方向 |
每行均值的数组 |
np.sum(axis=0) |
沿行方向统计(计算每列的总和) | axis=0:沿行方向 |
每列总和的数组 |
np.sum(axis=1) |
沿列方向统计(计算每行的总和) | axis=1:沿列方向 |
每行总和的数组 |
# -*- coding: utf-8 -*-
# 说明:演示按轴进行统计(沿特定维度)
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个 3x4 的矩阵
matrix = np.arange(12).reshape(3, 4)
print("示例矩阵(3行4列):")
print(matrix)
# 说明:按行统计(axis=0,计算每列)
# axis=0 表示沿着行方向(垂直方向)统计
column_mean = np.mean(matrix, axis=0)
print("\n每列的平均值(axis=0):", column_mean)
column_sum = np.sum(matrix, axis=0)
print("每列的总和(axis=0):", column_sum)
# 说明:按列统计(axis=1,计算每行)
# axis=1 表示沿着列方向(水平方向)统计
row_mean = np.mean(matrix, axis=1)
print("\n每行的平均值(axis=1):", row_mean)
row_sum = np.sum(matrix, axis=1)
print("每行的总和(axis=1):", row_sum)
# 说明:不指定轴(计算所有元素)
all_mean = np.mean(matrix)
print(f"\n所有元素的平均值(不指定轴):{all_mean}")9. 随机数 #
NumPy 的 random 模块提供了生成随机数的功能,常用于模拟、采样、数据增强等场景。
9.1 基本随机数生成 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.random.seed() |
设置随机种子(确保结果可复现) | seed:种子值 |
无 |
np.random.rand() |
生成 [0, 1) 区间的均匀分布随机数 | *d0, d1, ...:各维度大小 |
均匀分布随机数组 |
np.random.randn() |
生成标准正态分布随机数(均值0,标准差1) | *d0, d1, ...:各维度大小 |
标准正态分布随机数组 |
np.random.randint() |
生成指定区间的整数随机数 | low:最小值,high:最大值(不包含),size:大小 |
整数随机数组 |
np.random.normal() |
生成正态分布随机数 | loc:均值,scale:标准差,size:大小 |
正态分布随机数组 |
# -*- coding: utf-8 -*-
# 说明:演示 NumPy 的随机数生成
# 说明:导入 NumPy 库
import numpy as np
# 说明:设置随机种子(确保结果可复现)
# 设置相同的种子,每次运行会得到相同的随机数
np.random.seed(42)
# 说明:生成均匀分布的随机数
# rand() 函数生成 [0, 1) 区间的均匀分布随机数
# 参数 (2, 3) 表示生成一个 2 行 3 列的数组
uniform = np.random.rand(2, 3)
print("均匀分布随机数([0, 1) 区间):")
print(uniform)
# 说明:生成标准正态分布的随机数
# randn() 函数生成标准正态分布(均值为0,标准差为1)的随机数
normal = np.random.randn(2, 3)
print("\n标准正态分布随机数:")
print(normal)
# 说明:生成指定区间的整数随机数
# randint() 函数生成指定区间的整数随机数
# 参数:最小值(包含)、最大值(不包含)、大小
integers = np.random.randint(0, 10, size=(2, 3))
print("\n整数随机数(0-9):")
print(integers)
# 说明:生成指定分布和参数的随机数
# normal() 函数生成正态分布随机数
# 参数:均值、标准差、大小
custom_normal = np.random.normal(loc=100, scale=15, size=(2, 3))
print("\n自定义正态分布(均值100,标准差15):")
print(custom_normal)9.2 随机选择与打乱 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.random.choice() |
从数组中随机选择元素 | a:数组,size:选择数量,replace:是否允许重复 |
随机选择的元素数组 |
np.random.shuffle() |
原地打乱数组(修改原数组) | x:要打乱的数组 |
无(修改原数组) |
np.random.permutation() |
返回打乱后的新数组(不修改原数组) | x:要打乱的数组 |
打乱后的新数组 |
# -*- coding: utf-8 -*-
# 说明:演示随机选择和打乱操作
# 说明:导入 NumPy 库
import numpy as np
# 说明:设置随机种子
np.random.seed(42)
# 说明:从数组中选择随机元素
# choice() 函数从数组中随机选择元素
# 参数:数组、选择数量、是否允许重复
choices = np.array(["A", "B", "C", "D"])
selected = np.random.choice(choices, size=5, replace=True)
print("从数组中选择 5 个元素(允许重复):", selected)
# 说明:随机打乱数组
# shuffle() 函数原地打乱数组(修改原数组)
arr = np.arange(10)
print("\n原始数组:", arr)
np.random.shuffle(arr)
print("打乱后:", arr)
# 说明:返回打乱后的新数组(不修改原数组)
arr2 = np.arange(10)
print("\n原始数组:", arr2)
shuffled = np.random.permutation(arr2)
print("打乱后的新数组:", shuffled)
print("原数组未改变:", arr2)10. 文件操作 #
NumPy 可以方便地将数组保存到文件或从文件加载数组。
10.1 保存和加载 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.random.randn() |
生成标准正态分布随机数 | *d0, d1, ...:各维度大小 |
标准正态分布随机数组 |
np.savetxt() |
将数组保存为文本文件 | fname:文件名,X:数组,fmt:格式,delimiter:分隔符 |
无 |
np.loadtxt() |
从文本文件加载数组 | fname:文件名,delimiter:分隔符 |
加载的数组 |
np.save() |
将数组保存为二进制文件(.npy 格式) | file:文件名,arr:数组 |
无 |
np.load() |
从二进制文件加载数组(.npy 或 .npz 格式) | file:文件名 |
加载的数组或字典 |
np.allclose() |
检查两个数组是否近似相等 | a:数组1,b:数组2 |
布尔值(True/False) |
# -*- coding: utf-8 -*-
# 说明:演示如何保存和加载 NumPy 数组
# 说明:导入 NumPy 库
import numpy as np
import os
# 说明:创建示例数据
data = np.random.randn(5, 3)
print("原始数据:")
print(data)
# 说明:保存为文本文件
# savetxt() 函数将数组保存为文本文件
# 参数:文件名、数据、格式、分隔符
np.savetxt("data.txt", data, fmt="%.4f", delimiter=",")
print("\n数据已保存到 data.txt")
# 说明:从文本文件加载
# loadtxt() 函数从文本文件加载数组
loaded_txt = np.loadtxt("data.txt", delimiter=",")
print("\n从文本文件加载的数据:")
print(loaded_txt)
# 说明:保存为二进制文件(推荐,更快更小)
# save() 函数将数组保存为 .npy 格式(NumPy 二进制格式)
np.save("data.npy", data)
print("\n数据已保存到 data.npy")
# 说明:从二进制文件加载
# load() 函数从 .npy 文件加载数组
loaded_npy = np.load("data.npy")
print("\n从二进制文件加载的数据:")
print(loaded_npy)
# 说明:验证数据是否一致
if np.allclose(data, loaded_npy):
print("\n✓ 数据加载成功,与原始数据一致")
# 说明:清理临时文件(可选)
if os.path.exists("data.txt"):
os.remove("data.txt")
if os.path.exists("data.npy"):
os.remove("data.npy")10.2 批量保存和加载 #
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.savez() |
将多个数组保存到一个压缩文件(.npz 格式) | file:文件名,**kwds:关键字参数(数组名称=数组) |
无 |
np.load() |
加载 .npz 文件,返回类似字典的对象 | file:文件名 |
类似字典的对象,可用键访问数组 |
# -*- coding: utf-8 -*-
# 说明:演示如何批量保存和加载多个数组
# 说明:导入 NumPy 库
import numpy as np
import os
# 说明:创建多个数组
arr1 = np.array([1, 2, 3])
arr2 = np.array([[4, 5], [6, 7]])
arr3 = np.array([8, 9, 10])
# 说明:批量保存多个数组
# savez() 函数将多个数组保存到一个压缩文件
# 使用关键字参数指定每个数组的名称
np.savez("multiple_arrays.npz", array1=arr1, array2=arr2, array3=arr3)
print("多个数组已保存到 multiple_arrays.npz")
# 说明:从压缩文件加载
# load() 函数加载 .npz 文件,返回一个类似字典的对象
loaded = np.load("multiple_arrays.npz")
print("\n加载的数组:")
print("array1:", loaded["array1"])
print("array2:")
print(loaded["array2"])
print("array3:", loaded["array3"])
# 说明:查看文件中包含的所有数组名称
print("\n文件中包含的数组名称:", list(loaded.keys()))
# 说明:清理临时文件(可选)
if os.path.exists("multiple_arrays.npz"):
os.remove("multiple_arrays.npz")11. 实战案例:销售数据分析 #
下面是一个完整的实战案例,展示如何使用 NumPy 分析销售数据。
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.random.normal() |
生成正态分布随机数 | loc:均值,scale:标准差,size:大小 |
正态分布随机数组 |
.astype() |
转换数组的数据类型 | dtype:目标数据类型,如 int |
转换类型后的数组 |
.sum(axis=0) |
沿行方向求和(计算每列总和) | axis=0:沿行方向 |
每列总和的数组 |
.sum(axis=1) |
沿列方向求和(计算每行总和) | axis=1:沿列方向 |
每行总和的数组 |
.mean(axis=0) |
沿行方向求均值(计算每列均值) | axis=0:沿行方向 |
每列均值的数组 |
np.diff() |
计算相邻元素的差值 | a:数组 |
差值数组(长度比原数组少1) |
np.argmax() |
找出最大值的索引 | a:数组,axis:统计的轴(可选) |
最大值的索引 |
# -*- coding: utf-8 -*-
# 说明:实战案例 - 销售数据分析
# 演示如何使用 NumPy 分析模拟的销售数据
# 说明:导入 NumPy 库
import numpy as np
# 说明:设置随机种子,确保结果可复现
np.random.seed(0)
# 说明:生成模拟的销售数据
# 生成 12 个月 × 4 个产品的销售数据
# normal() 生成正态分布随机数:均值 1000,标准差 200
# astype(int) 将浮点数转换为整数
sales = np.random.normal(loc=1000, scale=200, size=(12, 4)).astype(int)
products = np.array(["产品A", "产品B", "产品C", "产品D"])
# 说明:打印原始数据
print("月度销量矩阵(12个月 × 4个产品):")
print(sales)
print(f"形状:{sales.shape}\n")
# 说明:计算每个产品的总销售额
# sum(axis=0) 计算每列的总和(每个产品的全年总销售额)
total_by_product = sales.sum(axis=0)
print("每个产品的全年总销售额:")
for prod, total in zip(products, total_by_product):
print(f" {prod}:{total:,}")
# 说明:计算每个产品的平均月销售额
avg_by_product = sales.mean(axis=0)
print("\n每个产品的平均月销售额:")
for prod, avg in zip(products, avg_by_product):
print(f" {prod}:{avg:.2f}")
# 说明:计算每个月的总销售额
# sum(axis=1) 计算每行的总和(每个月的总销售额)
monthly_total = sales.sum(axis=1)
print(f"\n每个月的总销售额:{monthly_total}")
# 说明:计算月度增长率
# diff() 函数计算相邻元素的差值
# 计算增长率:差值 / 上月的销售额 * 100
growth = np.diff(monthly_total) / monthly_total[:-1] * 100
print("\n月度增长率(%):")
for i, g in enumerate(growth, 1):
print(f" 第{i}月到第{i+1}月:{g:.2f}%")
# 说明:找出销售最好的月份和产品
best_month_idx = np.argmax(monthly_total)
best_month_sales = monthly_total[best_month_idx]
print(f"\n销售最好的月份:第{best_month_idx + 1}月,销售额:{best_month_sales:,}")
# 说明:找出每个产品销量最好的月份
print("\n每个产品销量最好的月份:")
for i, prod in enumerate(products):
best_month = np.argmax(sales[:, i]) + 1 # +1 因为月份从1开始
best_sales = sales[best_month - 1, i]
print(f" {prod}:第{best_month}月,销量:{best_sales:,}")12. 性能优化与常见问题 #
在使用 NumPy 时,了解一些优化技巧和常见问题有助于提高代码效率。
12.1 向量化 vs 循环 #
NumPy 的向量化计算比 Python 循环快得多。
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.random.rand() |
生成 [0, 1) 区间的均匀分布随机数 | *d0, d1, ...:各维度大小 |
均匀分布随机数组 |
arr * arr |
向量化乘法(对应元素相乘) | 两个数组 | 相乘后的数组 |
np.allclose() |
检查两个数组是否近似相等 | a:数组1,b:数组2 |
布尔值(True/False) |
# -*- coding: utf-8 -*-
# 说明:演示向量化计算与循环的性能对比
# 说明:导入必要的库
import numpy as np
import time
# 说明:创建一个大型数组
arr = np.random.rand(1_000_000) # 100 万个元素
# 说明:方法1:使用 Python 循环
# 这是慢的方法,逐个元素计算
start = time.time()
loop_result = np.array([x * x for x in arr])
loop_time = time.time() - start
# 说明:方法2:使用 NumPy 向量化
# 这是快的方法,对整个数组进行运算
start = time.time()
np_result = arr * arr
np_time = time.time() - start
# 说明:比较结果
print(f"Python 循环耗时:{loop_time:.4f} 秒")
print(f"NumPy 向量化耗时:{np_time:.4f} 秒")
print(f"速度提升:{loop_time / np_time:.1f} 倍")
# 说明:验证结果是否一致
if np.allclose(loop_result, np_result):
print("\n✓ 两种方法结果一致,但向量化更快")12.2 数据类型选择 #
合理选择数据类型可以节省内存。
本代码块中使用的 NumPy 方法和属性:
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.array(..., dtype=...) |
创建指定数据类型的数组 | object:数据,dtype:数据类型 |
指定类型的数组 |
.dtype |
获取数组的数据类型 | 无(属性) | 数据类型对象 |
.nbytes |
获取数组占用的总字节数 | 无(属性) | 总字节数(整数) |
.astype() |
转换数组的数据类型 | dtype:目标数据类型 |
转换类型后的数组 |
# -*- coding: utf-8 -*-
# 说明:演示数据类型对内存的影响
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建相同数据的数组,但使用不同的数据类型
arr_int32 = np.array([1, 2, 3, 4], dtype=np.int32)
arr_int64 = np.array([1, 2, 3, 4], dtype=np.int64)
arr_float64 = np.array([1, 2, 3, 4], dtype=np.float64)
# 说明:查看每个数组的内存占用
print(f"int32 数组大小:{arr_int32.nbytes} 字节")
print(f"int64 数组大小:{arr_int64.nbytes} 字节")
print(f"float64 数组大小:{arr_float64.nbytes} 字节")
# 说明:查看数据类型
print(f"\nint32 数据类型:{arr_int32.dtype}")
print(f"int64 数据类型:{arr_int64.dtype}")
print(f"float64 数据类型:{arr_float64.dtype}")
# 说明:转换数据类型
# astype() 方法可以转换数组的数据类型
arr_float = arr_int32.astype(np.float32)
print(f"\n转换为 float32:{arr_float.dtype}")12.3 广播机制 #
广播机制允许不同形状的数组进行运算。
本代码块中使用的 NumPy 方法和操作:
| 方法/操作 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
np.arange() |
创建等差数列 | start:起始值,stop:结束值(不包含) |
等差数列 |
.reshape() |
改变数组形状 | shape:新形状 |
重塑后的数组 |
arr1 + arr2 |
数组加法(支持广播) | 两个数组(形状可不同,但需兼容) | 相加后的数组 |
arr + scalar |
数组与标量相加(广播) | arr:数组,scalar:标量 |
每个元素都加上标量的数组 |
# -*- coding: utf-8 -*-
# 说明:演示 NumPy 的广播机制
# 说明:导入 NumPy 库
import numpy as np
# 说明:创建一个矩阵和一个向量
matrix = np.arange(12).reshape(3, 4)
vector = np.array([10, 20, 30, 40])
print("矩阵:")
print(matrix)
print(f"\n向量:{vector}")
print(f"向量形状:{vector.shape}")
# 说明:广播:向量会自动扩展以匹配矩阵的形状
# 这里向量会扩展为 3x4 矩阵,每一行都是 [10, 20, 30, 40]
result = matrix + vector
print("\n矩阵 + 向量(广播):")
print(result)
# 说明:标量广播
scalar = 100
result2 = matrix + scalar
print("\n矩阵 + 标量(广播):")
print(result2)12.4 常见问题 #
本代码块中使用的 NumPy 方法和操作:
| 方法/操作 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
arr[start:end] |
切片操作(返回视图) | start:起始索引,end:结束索引 |
切片数组(视图) |
.copy() |
创建数组的副本 | 无 | 数组的独立副本 |
arr1 + arr2 |
数组加法(广播) | 两个数组 | 相加后的数组 |
arr / scalar |
数组除法(自动转换为浮点数) | arr:数组,scalar:标量 |
相除后的数组(浮点型) |
# -*- coding: utf-8 -*-
# 说明:常见问题和解决方案
# 说明:导入 NumPy 库
import numpy as np
# 说明:问题1:修改数组时的视图 vs 副本
print("问题1:视图 vs 副本")
arr = np.array([1, 2, 3, 4, 5])
view = arr[1:4] # 这是视图(引用)
view[0] = 999 # 修改视图会影响原数组
print(f"原数组被修改:{arr}")
arr2 = np.array([1, 2, 3, 4, 5])
copy = arr2[1:4].copy() # 这是副本(独立)
copy[0] = 999
print(f"原数组未改变:{arr2}")
# 说明:问题2:数组形状不匹配
print("\n问题2:形状不匹配时的处理")
a = np.array([[1, 2], [3, 4]])
b = np.array([5, 6])
try:
# 这可能会出错,因为形状不匹配
result = a + b
print("运算成功(广播):")
print(result)
except Exception as e:
print(f"错误:{e}")
# 说明:问题3:整数除法的陷阱
print("\n问题3:整数除法的结果")
arr = np.array([1, 2, 3, 4])
result = arr / 2 # 即使原数组是整数,结果也是浮点数
print(f"整数数组除以2:{result}, 类型:{result.dtype}")