numpy库详解

一、NumPy简介

NumPy(Numerical Python) 是 Python 中用于科学计算的核心库,提供了高性能的多维数组对象ndarray)以及大量用于数组操作的函数。其特点包括:

  • 高效存储与计算:基于 C 语言实现,数组存储紧凑,运算速度远超 Python 原生列表。
  • 向量化操作:避免显式循环,大幅提升代码简洁性和执行效率。
  • 广播机制:支持不同形状数组间的运算,简化数据处理逻辑。
  • 集成性强:与 Pandas、SciPy、Matplotlib 等库深度整合,是数据分析和机器学习的基础。

二、核心概念:ndarray 数组

ndarray 的特点

  • 同质性:所有元素类型相同(由dtype指定,如int32float64等)。
  • 多维性:通过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:指定分割方式,支持两种形式:
    1. 整数:将数组均分为指定数量的子数组(需确保能整除)。
    2. 一维数组:指定分割点的索引位置(沿轴 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 数据科学领域的必备技能。

posted @ 2025-07-14 10:45  郭慕荣  阅读(126)  评论(0)    收藏  举报