numpy库详解
一、NumPy简介
NumPy(Numerical Python) 是 Python 中用于科学计算的核心库,提供了高性能的多维数组对象(ndarray
)以及大量用于数组操作的函数。其特点包括:
- 高效存储与计算:基于 C 语言实现,数组存储紧凑,运算速度远超 Python 原生列表。
- 向量化操作:避免显式循环,大幅提升代码简洁性和执行效率。
- 广播机制:支持不同形状数组间的运算,简化数据处理逻辑。
- 集成性强:与 Pandas、SciPy、Matplotlib 等库深度整合,是数据分析和机器学习的基础。
二、核心概念:ndarray 数组
ndarray 的特点
- 同质性:所有元素类型相同(由
dtype
指定,如int32
、float64
等)。 - 多维性:通过
shape
属性表示各维度大小(例如二维数组形状为(行数, 列数)
)。 - 内存连续:元素在内存中连续存储,便于快速访问和运算。
2. 创建 ndarray 的常见方式
(1)从 Python 列表转换
import numpy as np
# 一维数组
arr1 = np.array([1, 2, 3, 4])
# 二维数组
arr2 = np.array([[1, 2], [3, 4]])
(2)使用random模块生成数组
在 NumPy 中,可以使用
numpy.random
模块高效地生成各种随机数组
import numpy as np
#生成均匀分布的随机数组
#生成 [0, 1) 范围内的均匀分布随机浮点数
arr = np.random.rand(3, 4) #生成一个 3x4 的随机浮点数数组
#生成指定范围内的均匀分布随机浮点数。
arr_1 = np.random.uniform(-1, 1, 5) #生成 5 个 [-1, 1] 范围内的随机数
#生成正态分布的随机数组
#生成标准正态分布(均值 = 0,标准差 = 1)的随机浮点数
arr_2 = np.random.randn(2, 2) #生成一个 2x2 的标准正态分布数组
#生成指定均值和标准差的正态分布随机数。
arr_3 = np.random.normal(5, 2, 3) #生成均值为 5,标准差为 2 的 3 个随机数
#生成随机整数数组
#生成指定范围内的随机整数
arr_4 = np.random.randint(0, 10, size=(2, 3)) #生成[0,10)范围内的2x3整数数组
#随机打乱与抽样
#就地打乱数组的顺序(仅对一维数组有效)
arr_5 = np.array([1, 2, 3, 4, 5])
np.random.shuffle(arr_5)
print(arr) # 输出示例:[3 5 1 4 2]
#返回原数组的随机排列(不改变原数组)
arr_6 = np.array([1, 2, 3, 4, 5])
permuted = np.random.permutation(arr_6)
print(permuted) # 输出打乱后的数组
print(arr_6) # 原数组不变
#从一维数组中随机抽样
samples = np.random.choice(10, 3, replace=False) # 从 [0, 10) 中随机选择 3 个不重复的数
print(samples) # 输出示例:[4 7 1]
#固定随机种子(可复现性)
#使用 np.random.seed() 可以固定随机数生成器的种子,确保结果可复现
np.random.seed(42) # 设置种子为 42
print(np.random.rand(2)) # 每次运行都会得到相同的结果 输出:[0.37454012 0.95071431]
#高级分布
#泊松分布
arr_7 = np.random.poisson(3, 5) # 生成泊松分布(λ=3)的 5 个随机数
print(arr_7) #输出示例:[2 4 3 5 2]
#二项分布
arr_8 = np.random.binomial(n=10, p=0.5, size=5) #n:试验次数(非负整数)p:每次实验的成功概率(范围[0,1]) size:输出数组的形状(可选)。若不指定,则返回单个随机数
print(arr_8) # 输出示例:[4 6 5 7 5]
#卡方分布
arr_9 = np.random.chisquare(df=5, size=5) #df:自由度,必须为正数(整数或浮点数) size:输出数组的形状,不指定则返回单个随机数
print(arr_9) # 输出示例:[6.23 3.78 4.91 8.35 5.67]
(2)创建指定形状的数组
函数 | 说明 | 示例 |
---|---|---|
np.zeros |
全 0 数组 | np.zeros((3, 4)) → 3×4 全 0 数组 |
np.zeros_like(ndarr) |
以 ndarr 相同维度创建元素全为 0 数组 | |
np.ones |
全 1 数组 | np.ones((2, 2)) → 2×2 全 1 数组 |
np.ones_like(ndarr) |
以 ndarr 相同维度创建元素全为 1 数组 | |
np.empty |
未初始化数组(值为随机数) | np.empty(5) → 长度为 5 的数组 |
np.empty_like(ndarr) |
以 ndarr 相同维度创建空数组 | |
np.arange |
等差序列(类似 Python 的 range) | np.arange(0, 10, 2) → [0,2,4,6,8] |
np.linspace |
等距分点序列 | np.linspace(0, 10, 5) → 0 到 10 均匀分 5 点 |
numpy.full(shape, fill_value, dtype=None, order='C') |
创建元素全为fill_value 的数组 | np.full((2, 2), 10) |
(3)特殊数组
# 单位矩阵(对角线为1,其余为0)
identity_matrix = np.eye(3) # 3×3单位矩阵
# 对角矩阵
diag_matrix = np.diag([1, 2, 3]) # 对角线元素为[1,2,3]
3. ndarray 的属性
属性 | 说明 | 示例 |
---|---|---|
ndim |
维度数 | arr.ndim → 2(二维数组) |
shape |
各维度大小元组 | arr.shape → (3, 4) |
size |
元素总数 | arr.size → 12 |
dtype |
元素数据类型 | arr.dtype → dtype('int64') |
itemsize |
单个元素占用字节数 | arr.itemsize → 8(int64 占 8 字节) |
三、数组操作与运算
索引与切片
(1)一维数组
一维数组的索引与 Python 列表类似,从 0 开始,支持负数索引(从后向前)。
语法:
array[start:stop:step]
,其中:start
:起始索引(包含),默认为 0。stop
:结束索引(不包含),默认为数组长度。step
:步长,默认为 1。
arr = np.array([10, 20, 30, 40, 50])
print(arr[0]) # 第一个元素 → 10
print(arr[1:4]) # 切片[1,4) → [20, 30, 40]
print(arr[-1]) # 最后一个元素 → 50
print(arr[:3]) # 输出:[10 20 30](索引 0 到 2)
print(arr[2:]) # 输出:[30 40 50](索引 2 到最后)
print(arr[::2]) # 输出:[10 30 50](每隔一个元素)
print(arr[::-1]) # 输出:[50 40 30 20 10](反转数组)
(2)二维数组(类似矩阵)
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix[1, 2]) # 第2行第3列元素 → 6(行、列从0开始)
print(matrix[:, 1]) # 所有行,第2列 → [2, 5, 8]
print(matrix[1:, :2]) # 第2行及之后,前2列 → [[4,5], [7,8]]
(3)布尔索引(筛选符合条件的元素)
arr = np.array([1, 2, 3, 4, 5])
mask = arr > 3 # 生成布尔数组 [False, False, False, True, True]
print(arr[mask]) # 筛选结果 → [4, 5]
(4) 整数索引(使用整数数组指定要访问的元素位置)
arr = np.array([10, 20, 30, 40, 50])
indices = np.array([0, 3, 4])
print(arr[indices]) # 输出:[10 40 50]
# 对多维数组使用整数索引
arr_2d = np.array([[1, 2], [3, 4], [5, 6]])
rows = np.array([0, 1, 2])
cols = np.array([1, 0, 1])
print(arr_2d[rows, cols]) # 输出:[2 3 6]
2. 数组运算
(1)算术运算(向量化)
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b) # 对应元素相加 → [5, 7, 9]
print(a * b) # 输出:[4 10 18]
print(a * 2) # 所有元素乘2 → [2, 4, 6]
print(a ** 2) # 元素平方 → [1, 4, 9]
(2)矩阵运算
使用
np.dot()
或@
运算符(Python 3.5+)
# 矩阵乘法(点积)
mat1 = np.array([[1, 2], [3, 4]])
mat2 = np.array([[5, 6], [7, 8]])
print(np.dot(mat1, mat2)) # 等价于 mat1 @ mat2
# 结果:
# [[1*5+2*7, 1*6+2*8],
# [3*5+4*7, 3*6+4*8]] → [[19, 22], [43, 50]]
# 转置
a = np.array([[1, 2], [3, 4]])
print(a.T) # 输出:[[1 3], [2 4]]
#逆矩阵
print(np.linalg.inv(a))
(3)广播机制(自动适配形状差异)
广播是 NumPy 处理不同形状数组运算的机制。当数组形状不匹配时,较小的数组会被 “广播” 以匹配较大数组的形状。
规则:1. 从右到左比较数组维度,若维度相等或其中一个为 1,则可以广播。
2. 广播后,每个维度的大小为两个数组对应维度的最大值。
# 一维数组与标量运算(广播标量)
arr = np.array([1, 2, 3])
print(arr + 10) # [11, 12, 13]
# 二维数组与一维数组运算(广播维度)
matrix = np.array([[1, 2, 3], [4, 5, 6]]) # 形状(2,3)
vec = np.array([10, 20, 30]) # 形状(3,)
print(matrix + vec) # 每行与vec相加 → [[11,22,33], [14,25,36]]
(4)数学函数(元素级)
NumPy 提供了大量数学函数,对数组每个元素进行操作
a = np.array([1, 2, 3])
# 三角函数
print(np.sin(a)) # 正弦
print(np.cos(a)) # 余弦
# 指数和对数
print(np.exp(a)) # e^x
print(np.log(a)) # 自然对数
# 平方根
print(np.sqrt(a)) # 平方根
(5)统计运算
a = np.array([[1, 2], [3, 4]])
print(np.sum(a)) # 总和:10
print(np.mean(a)) # 平均值:2.5
print(np.std(a)) # 标准差:1.118
print(np.min(a)) # 最小值:1
print(np.max(a)) # 最大值:4
print(np.argmin(a)) # 最小值索引:0
print(np.argmax(a)) # 最大值索引:3
# 按列求和(轴=0)
print(np.sum(a, axis=0)) # 输出:[4 6]
# 按行求平均值(轴=1)
print(np.mean(a, axis=1)) # 输出:[1.5 3.5]
(6)逻辑运算
# 元素级比较
a = np.array([1, 2, 3])
b = np.array([2, 2, 2])
print(a > b) # 输出:[False False True]
print(a == b) # 输出:[False True False]
# 布尔数组操作
# 统计 True 的数量
print(np.sum(a > b)) # 输出:1
# 检查是否所有元素满足条件
print(np.all(a > 0)) # 输出:True
# 检查是否有元素满足条件
print(np.any(a > 2)) # 输出:True
(7)条件运算
# 使用 np.where() 进行条件选择
# a = np.array([1, -2, 3, -4])
# 将负数替换为 0
print(np.where(a < 0, 0, a)) # 输出:[1 0 3 0]
(8)线性代数运算
a = np.array([[1, 2], [3, 4]])
# 特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(a)
print(eigenvalues) # 特征值
print(eigenvectors) # 特征向量
# 奇异值分解(SVD)
U, s, Vt = np.linalg.svd(a)
print(U, s, Vt)
# 行列式和迹
print(np.linalg.det(a)) # 行列式:-2.0
print(np.trace(a)) # 迹(对角线元素和):5
3. 数组变形与组合
(1)形状修改
arr = np.array([1, 2, 3, 4, 5, 6])
# 转为2×3矩阵
reshaped_arr = arr.reshape((2, 3)) # 形状变为(2,3)
# 展平为一维数组
flatten_arr = reshaped_arr.flatten() # [1,2,3,4,5,6] 返回视图(不复制数据)
ravelled = arr.ravel() # 结果相同,但可能是视图
# 当某个维度为 -1 时,NumPy 会根据数组总元素数自动计算该维度的大小
arr_1 = np.arange(12).reshape(2, 6)
print(arr_1)
arr.reshape(4, -1) # 等价于 reshape(4, 3)
(2)数组拼接
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 按行拼接(垂直方向) 等价于 vertical = np.concatenate([a, b], axis=0)
vertical_stack = np.vstack((a, b)) # [[1,2],[3,4],[5,6],[7,8]]
# 按列拼接(水平方向) 等价于 horizontal = np.concatenate([a, b], axis=1)
horizontal_stack = np.hstack((a, b)) # [[1,2,5,6],[3,4,7,8]]
# np.stack():创建新维度
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 沿新轴 0 堆叠(结果形状:(2, 3))
stacked_0 = np.stack([a, b], axis=0)
print(stacked_0)
# 输出:
# [[1 2 3]
# [4 5 6]]
# 沿新轴 1 堆叠(结果形状:(3, 2))
stacked_1 = np.stack([a, b], axis=1)
print(stacked_1)
# 输出:
# [[1 4]
# [2 5]
# [3 6]]
(3)数组拆分
arr = np.array([1, 2, 3, 4, 5, 6])
# 等分为3个数组
split_arrays = np.split(arr, 3) # [array([1,2]), array([3,4]), array([5,6])]
# 指定分割点
subarrays = np.split(arr, [2, 4]) #[array([1, 2]), array([3, 4]), array([5, 6])]
np.vsplit(ary, indices_or_sections)
ary
:需要分割的输入数组,必须是至少二维的数组(如 2D 矩阵、3D 张量)。indices_or_sections
:指定分割方式,支持两种形式:
- 整数:将数组均分为指定数量的子数组(需确保能整除)。
- 一维数组:指定分割点的索引位置(沿轴 0)。
# 二维数组按列拆分
arr = np.arange(12).reshape(4, 3)
# 垂直分割(沿轴 0)
v_splits = np.vsplit(arr, 2)
print(v_splits)
# 输出:
# [array([[0, 1, 2], [3, 4, 5]]), array([[6, 7, 8], [9, 10, 11]])]
# 水平分割(沿轴 1)
h_splits = np.hsplit(arr, 3)
print(h_splits)
# 输出:[array([[0], [3], [6], [9]]), array([[1], [4], [7], [10]]), array([[2], [5], [8], [11]])]
四、常用函数与统计操作
1. 数学函数
函数 | 说明 | 示例 |
---|---|---|
np.sqrt |
平方根 | np.sqrt([4, 9]) → [2, 3] |
np.exp |
指数运算(e^x) | np.exp([1, 2]) → [e, e²] |
np.log |
自然对数(lnx) | np.log([1, e]) → [0, 1] |
np.sin |
正弦函数 | np.sin(np.pi/2) → 1.0 |
np.abs |
绝对值 | np.abs([-1, 2]) → [1, 2] |
2. 统计函数
函数 | 说明 | 示例 |
---|---|---|
np.sum |
求和 | np.sum(arr) → 元素总和 |
np.mean |
均值 | np.mean(arr) → 平均值 |
np.std |
标准差 | np.std(arr) → 标准差 |
np.max |
最大值 | np.max(arr) → 最大值 |
np.min |
最小值 | np.min(arr) → 最小值 |
np.argmax |
最大值索引 | np.argmax(arr) → 最大值位置索引 |
np.sort |
排序 | np.sort(arr) → 排序后的数组 |
3. 线性代数运算
# 求矩阵的逆
matrix = np.array([[1, 2], [3, 4]])
inverse_matrix = np.linalg.inv(matrix) # 逆矩阵
# 求行列式
det = np.linalg.det(matrix) # 行列式值(1×4 - 2×3 = -2)
# 特征值与特征向量
eigenvalues, eigenvectors = np.linalg.eig(matrix)
五、IO 操作与性能优化
1. 数据读写
(1)保存为文本文件
arr = np.array([1, 2, 3, 4])
np.savetxt('data.txt', arr, fmt='%d') # 保存为整数格式
loaded_arr = np.loadtxt('data.txt', dtype=int) # 读取文件
(2)保存为二进制文件(高效)
np.save('data.npy', arr) # 保存为.npy文件
loaded_arr = np.load('data.npy') # 读取.npy文件
(3)读写 CSV 文件(需配合 Pandas)
import pandas as pd
df = pd.read_csv('data.csv')
arr = df.values # 转换为NumPy数组
2. 性能优化技巧
- 避免循环:尽量用向量化操作替代
for
循环。 - 数据类型指定:使用合适的
dtype
(如float32
替代float64
)减少内存占用。 - 内存视图:通过
view()
方法避免数据拷贝,节约内存。 - 并行计算:利用 NumPy 的多线程特性(部分函数自动支持)。
六、应用场景
- 科学计算:物理模拟、信号处理等。
- 数据分析:配合 Pandas 处理大规模数据集。
- 机器学习:作为 TensorFlow、PyTorch 等框架的底层数据结构(可无缝转换为张量)。
- 图像处理:图像像素数据存储与运算(如 OpenCV 集成)。
通过掌握 NumPy 的核心功能,可显著提升数据处理和科学计算的效率,是 Python 数据科学领域的必备技能。
郭慕荣博客园