目录
一、数组属性与创建
二、基础运算
三、索引
四、数组合并
五、数组分割
六、数组的复制 (copy)
七、周期信号生成
NumPy (Numerical Python) 是 Python 中用于科学计算的核心库。它提供了一个高性能的多维数组对象ndarray,以及用于操作这些数组的大量工具。
一、数组属性与创建
数组 (
ndarray)- 这是 NumPy 的核心数据结构,用于存储同类型数据的多维容器。
import numpy as np # 创建一维数组 a = np.array([1, 2, 3, 4]) print(a) # 输出: [1 2 3 4] # 创建二维数组 b = np.array([[1, 2, 3], [4, 5, 6]]) print(b) # 输出: # [[1 2 3] # [4 5 6]]数据类型 (
dtype)- 指定数组中元素的数据类型(如
int32,float64,complex,bool_,object_等)。 - 创建时指定(默认64),或查看已有数组的数据类型。
c = np.array([1, 2, 3], dtype=np.float64) print(c.dtype) # 输出: float64- 指定数组中元素的数据类型(如
维度 (
ndim)- 返回数组的维数(轴的数量)。
print(a.ndim) # 输出: 1 (一维) print(b.ndim) # 输出: 2 (二维)形状 (
shape)- 返回一个元组,表示数组在每个维度上的大小。
print(a.shape) # 输出: (4,) (长度为4的一维数组) print(b.shape) # 输出: (2, 3) (2行3列的二维数组)元素总数 (
size)- 返回数组中元素的总个数。
print(a.size) # 输出: 4 print(b.size) # 输出: 6创建特定数组
np.zeros(shape): 创建指定形状的数组,元素全部填充为0。np.ones(shape): 创建指定形状的数组,元素全部填充为1。np.empty(shape): 创建指定形状的数组,元素初始值为内存中的随机值(未初始化)。np.arange([start,] stop[, step]): 创建等差序列的一维数组,类似于 Python 的range,但返回数组。np.linspace(start, stop, num): 创建指定数量num个元素的等差序列一维数组,在start和stop之间(包含端点)。np.random: 子模块,用于生成随机数数组。np.random.rand(d0, d1, ..., dn): 生成在[0, 1)区间均匀分布的随机浮点数数组,形状由参数指定。np.random.randn(d0, d1, ..., dn): 生成标准正态分布(均值为0,标准差为1)的随机浮点数数组。np.random.randint(low, high, size): 生成在[low, high)区间内的随机整数数组,形状由size指定。
# 创建 2x3 的全零数组 zeros_arr = np.zeros((2, 3)) print(zeros_arr) # 创建 3 个元素的全一数组 ones_arr = np.ones(3) print(ones_arr) # 输出: [1. 1. 1.] # 创建未初始化的 2x2 数组 (值随机) empty_arr = np.empty((2, 2)) print(empty_arr) # 创建从0到9的一维数组 arange_arr = np.arange(10) print(arange_arr) # 输出: [0 1 2 3 4 5 6 7 8 9] # 创建从0到10(包含10)的5个等间隔点 linspace_arr = np.linspace(0, 10, 5) print(linspace_arr) # 输出: [ 0. 2.5 5. 7.5 10. ] # 生成 2x2 的 [0, 1) 均匀分布随机数 rand_arr = np.random.rand(2, 2) print(rand_arr) # 生成 3 个标准正态分布随机数 randn_arr = np.random.randn(3) print(randn_arr) # 生成 5 个 [1, 10) 的随机整数 randint_arr = np.random.randint(1, 10, 5) print(randint_arr)改变形状 (
reshape)- 返回一个改变了形状的数组视图(不改变原数据)。新形状的元素总数必须与原数组相同。
arr = np.arange(12) # [0, 1, 2, ..., 11] reshaped_arr = arr.reshape((3, 4)) # 变成 3行4列 print(reshaped_arr) # 输出: # [[ 0 1 2 3] # [ 4 5 6 7] # [ 8 9 10 11]] # 尝试错误形状会报错 # arr.reshape((3, 5)) # ValueError: cannot reshape array of size 12 into shape (3,5)
二、基础运算
NumPy 数组支持高效的向量化操作。
逐个元素运算
- 对数组中的每个元素进行相同的算术运算(
+,-,*,/,**等)、比较运算(==,!=,>,<,>=,<=)和逻辑运算(&,|,~)。这些操作返回一个新的布尔数组或数值数组。
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) # 输出: [1 4 9] # 比较 print(a > 2) # 输出: [False False True] print(a == b) # 输出: [False False False] # 三角函数 (作用于每个元素) print(np.sin(a)) # 输出: [0.84147098 0.90929743 0.14112001]- 对数组中的每个元素进行相同的算术运算(
点乘 (
np.dot,@运算符)- 矩阵乘法。对于一维数组,是内积;对于二维数组,是标准矩阵乘法。
# 一维数组 (内积) vec1 = np.array([1, 2]) vec2 = np.array([3, 4]) dot_product = np.dot(vec1, vec2) # 1*3 + 2*4 = 11 print(dot_product) # 输出: 11 # 或者使用 @ 运算符 (Python 3.5+) print(vec1 @ vec2) # 输出: 11 # 二维数组 (矩阵乘法) mat1 = np.array([[1, 2], [3, 4]]) mat2 = np.array([[5, 6], [7, 8]]) mat_product = np.dot(mat1, mat2) # 或者 mat1 @ mat2 # 或者 mat1.dot(mat2) print(mat_product) # 输出: # [[19 22] # [43 50]] # 计算: [[1*5+2*7, 1*6+2*8], [3*5+4*7, 3*6+4*8]]聚合函数
- 对整个数组或沿某个轴进行统计计算。
np.sum(arr, axis=None): 求和。np.min(arr, axis=None),np.max(arr, axis=None): 最小值、最大值。np.mean(arr, axis=None): 平均值。np.average(arr, axis=None, weights=None): 加权平均值。np.median(arr, axis=None): 中位数。np.cumsum(arr, axis=None): 累积和。np.argmin(arr, axis=None),np.argmax(arr, axis=None): 返回最小值、最大值所在位置的索引。
axis参数:指定计算沿哪个轴进行。axis=0: 沿列(垂直方向)计算,结果减少一个维度(例如二维数组变成一维)。axis=1: 沿行(水平方向)计算。axis=None: 在整个数组上计算,得到一个标量值。
arr2d = np.array([[1, 2, 3], [4, 5, 6]]) # 整个数组求和 total_sum = np.sum(arr2d) print(total_sum) # 输出: 21 # 沿列求和 (axis=0) - 计算每列的和 col_sum = np.sum(arr2d, axis=0) print(col_sum) # 输出: [5 7 9] (1+4, 2+5, 3+6) # 沿行求和 (axis=1) - 计算每行的和 row_sum = np.sum(arr2d, axis=1) print(row_sum) # 输出: [6 15] (1+2+3, 4+5+6) # 最大值 print(np.max(arr2d)) # 输出: 6 # 沿列最大值 print(np.max(arr2d, axis=0)) # 输出: [4 5 6] # 沿行最大值 print(np.max(arr2d, axis=1)) # 输出: [3 6] # 平均值 print(np.mean(arr2d)) # 输出: 3.5 # 中位数 print(np.median(arr2d)) # 输出: 3.5 # 累积和 (整个数组展开) print(np.cumsum(arr2d)) # 输出: [ 1 3 6 10 15 21] # 最小值索引 (整个数组) print(np.argmin(arr2d)) # 输出: 0 (元素1在位置0) # 沿列最大值索引 print(np.argmax(arr2d, axis=0)) # 输出: [1 1 1] (第0列最大值4在第1行,第1列最大值5在第1行,第2列最大值6在第1行)- 对整个数组或沿某个轴进行统计计算。
条件查找 (
np.nonzero)- 返回数组中非零元素的索引。
arr = np.array([0, 1, 0, 3, 0, 5]) indices = np.nonzero(arr) print(indices) # 输出: (array([1, 3, 5]),) 表示索引1, 3, 5处非零 print(arr[indices]) # 输出: [1 3 5] (使用这些索引获取非零值)排序 (
np.sort)- 对数组进行排序(默认升序)。返回排序后的数组副本。
arr = np.array([3, 1, 4, 2]) sorted_arr = np.sort(arr) print(sorted_arr) # 输出: [1 2 3 4] # 原数组不变 print(arr) # 输出: [3 1 4 2]转置 (
np.transpose,.T属性)- 交换数组的维度。对于二维数组,就是交换行和列。
arr = np.array([[1, 2], [3, 4], [5, 6]]) print(arr) # [[1 2] # [3 4] # [5 6]] print(arr.T) # 或者 np.transpose(arr) # [[1 3 5] # [2 4 6]]裁剪 (
np.clip)- 将数组中的元素限制在指定的最小值和最大值范围内。小于
min的值设为min,大于max的值设为max。
arr = np.array([10, 5, 3, 15, 8]) clipped_arr = np.clip(arr, 4, 12) print(clipped_arr) # 输出: [10 5 4 12 8] (3->4, 15->12)- 将数组中的元素限制在指定的最小值和最大值范围内。小于
三、索引
NumPy 提供了强大的索引功能。
基本索引
- 使用整数索引获取单个元素或切片(类似于 Python 列表)。
- 对于多维数组,使用逗号分隔的索引元组。
arr = np.array([0, 1, 2, 3, 4, 5]) print(arr[0]) # 输出: 0 print(arr[1:4]) # 输出: [1 2 3] (索引1到3) arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(arr2d[0]) # 输出: [1 2 3] (第0行) print(arr2d[0, 1]) # 输出: 2 (第0行,第1列) print(arr2d[0:2]) # 输出: [[1 2 3] [4 5 6]] (第0行和第1行) print(arr2d[0:2, 1:3]) # 输出: [[2 3] [5 6]] (第0-1行,第1-2列)布尔索引
- 使用布尔数组(通常由条件表达式生成)来选择元素。
arr = np.array([5, 10, 15, 20, 25]) # 创建布尔数组: 哪些元素大于15? mask = arr > 15 print(mask) # 输出: [False False False True True] # 使用布尔索引选择元素 print(arr[mask]) # 输出: [20 25] # 一步完成 print(arr[arr > 15]) # 输出: [20 25]花式索引 (Fancy Indexing)
- 使用整数数组(或列表)来索引。返回一个副本,而不是视图。
arr = np.arange(0, 10, 1) # [0,1,2,3,4,5,6,7,8,9] # 选择索引为 [2, 4, 6] 的元素 indices = [2, 4, 6] print(arr[indices]) # 输出: [2 4 6] arr2d = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]) # 选择第0行和第2行 print(arr2d[[0, 2]]) # 输出: # [[1 2] # [5 6]]flat与flatten()
numpy的flat属性提供迭代器遍历数组所有元素,而flatten()方法返回展平后的一维数组副本。import numpy as np arr = np.array([[1, 2], [3, 4]]) # 使用flat迭代元素 for element in arr.flat: print(element) # 输出: 1, 2, 3, 4 # 使用flatten()获取展平数组 flattened = arr.flatten() print(flattened) # 输出: [1 2 3 4]
四、数组合并
将多个数组组合成一个更大的数组。
垂直堆叠 (
np.vstack)- 沿第一个轴(行方向,
axis=0)堆叠数组。要求所有数组的列数相同。
a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) vstacked = np.vstack((a, b)) print(vstacked) # 输出: # [[1 2 3] # [4 5 6]] c = np.array([[1], [2], [3]]) d = np.array([[4], [5], [6]]) vstacked2 = np.vstack((c, d)) print(vstacked2) # 输出: # [[1] # [2] # [3] # [4] # [5] # [6]]- 沿第一个轴(行方向,
水平堆叠 (
np.hstack)- 沿第二个轴(列方向,
axis=1)堆叠数组。要求所有数组的行数相同。
a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) hstacked = np.hstack((a, b)) print(hstacked) # 输出: [1 2 3 4 5 6] c = np.array([[1], [2], [3]]) d = np.array([[4], [5], [6]]) hstacked2 = np.hstack((c, d)) print(hstacked2) # 输出: # [[1 4] # [2 5] # [3 6]]- 沿第二个轴(列方向,
增加新维度 (
np.newaxis/None)- 用于在特定位置插入一个新的长度为1的轴,改变数组的形状,使其可以与其他数组进行堆叠或广播。
a = np.array([1, 2, 3]) print(a.shape) # (3,) # 将其变成行向量 (1 行, 3 列) row_vec = a[np.newaxis, :] # 或者 a[None, :] print(row_vec) # 输出: [[1 2 3]] print(row_vec.shape) # (1, 3) # 将其变成列向量 (3 行, 1 列) col_vec = a[:, np.newaxis] # 或者 a[:, None] print(col_vec) # 输出: # [[1] # [2] # [3]] print(col_vec.shape) # (3, 1) # 现在可以用 vstack/hstack 与其他数组合并 b = np.array([4, 5, 6])[:, None] # 也变成列向量 hstacked_cols = np.hstack((col_vec, b)) print(hstacked_cols) # 输出: # [[1 4] # [2 5] # [3 6]]通用连接 (
np.concatenate)- 沿指定轴连接数组序列。功能比
vstack和hstack更通用。 np.concatenate((a1, a2, ...), axis=0)
a = np.array([[1, 2], [3, 4]]) b = np.array([[5, 6]]) # 沿行 (axis=0) 连接,要求列数相同 concat_rows = np.concatenate((a, b), axis=0) print(concat_rows) # 输出: # [[1 2] # [3 4] # [5 6]] # 沿列 (axis=1) 连接,要求行数相同 c = np.array([[7], [8]]) concat_cols = np.concatenate((a, c), axis=1) print(concat_cols) # 输出: # [[1 2 7] # [3 4 8]]- 沿指定轴连接数组序列。功能比
五、数组分割
将一个数组拆分成多个较小的数组。
均等分割 (
np.split,np.array_split)np.split(ary, indices_or_sections, axis=0): 将数组沿指定轴分割成多个子数组。indices_or_sections: 如果是一个整数N,表示将数组均等分割成N份。如果是一个索引列表[i1, i2, ...],表示在索引i1,i2, ... 处进行分割。
np.array_split(ary, indices_or_sections, axis=0): 功能与split类似,但允许不均等分割(当不能整除时,最后几个子数组会包含较少的元素)。
arr = np.arange(10) # [0,1,2,3,4,5,6,7,8,9] # 均等分割成2份 (要求能整除) split_2 = np.split(arr, 2) print(split_2) # [array([0,1,2,3,4]), array([5,6,7,8,9])] # 在索引3和7处分割 split_indices = np.split(arr, [3, 7]) print(split_indices) # [array([0,1,2]), array([3,4,5,6]), array([7,8,9])] # 不均等分割成3份 (使用 array_split) arrsplit_3 = np.array_split(arr, 3) print(arrsplit_3) # [array([0,1,2,3]), array([4,5,6]), array([7,8,9])] 或类似分布垂直分割 (
np.vsplit)- 沿垂直方向(行方向,
axis=0)分割数组。相当于split函数设置axis=0。
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) # 分割成2个行数相等的数组 vsplit_2 = np.vsplit(arr2d, 2) print(vsplit_2) # [array([[1, 2, 3], [4, 5, 6]]), array([[7, 8, 9], [10, 11, 12]])] # 在第2行处分割 vsplit_idx = np.vsplit(arr2d, [2]) print(vsplit_idx) # [array([[1, 2, 3], [4, 5, 6]]), array([[7, 8, 9], [10, 11, 12]])] (同上)- 沿垂直方向(行方向,
水平分割 (
np.hsplit)- 沿水平方向(列方向,
axis=1)分割数组。相当于split函数设置axis=1。
arr2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) # 分割成2个列数相等的数组 hsplit_2 = np.hsplit(arr2d, 2) print(hsplit_2) # [array([[1, 2], [5, 6]]), array([[3, 4], [7, 8]])] # 在第2列处分割 hsplit_idx = np.hsplit(arr2d, [2]) print(hsplit_idx) # [array([[1, 2], [5, 6]]), array([[3, 4], [7, 8]])] (同上) # 不均等分割 (使用 array_split 或指定索引列表) hsplit_uneven = np.hsplit(arr2d, [1, 3]) # 在索引1和3处分割 print(hsplit_uneven) # [array([[1], [5]]), array([[2, 3], [6, 7]]), array([[4], [8]])]- 沿水平方向(列方向,
六、数组的复制 (copy)
NumPy 数组的赋值操作 (b = a) 是浅拷贝。它不会创建新的数据副本,而是让新变量b指向与原变量a相同的底层数据(内存块)。因此,修改b也会改变a,反之亦然。
a = np.array([1, 2, 3]) b = a # b 是 a 的一个视图 (view),指向相同的数据 b[0] = 99 # 通过 b 修改数据 print(a) # 输出: [99 2 3] # a 也被修改了! print(b) # 输出: [99 2 3]如果需要创建一个数组的独立副本(深拷贝),使其数据与原数组完全分离,必须使用np.copy函数或数组的copy()方法:
a = np.array([1, 2, 3]) c = a.copy() # 或者 c = np.copy(a) c[0] = 99 # 修改 c 的数据 print(a) # 输出: [1 2 3] # a 保持不变 print(c) # 输出: [99 2 3]七、周期信号生成
- 参数设置:这里A=1.0(振幅为1),f=5(频率5Hz),fs=1000(采样频率1000Hz),T=1(信号持续1秒)。采样点数计算为fs*T = 1000。
- 时间轴生成:
np.linspace(0, T, int(fs * T))创建一个从0到1秒的数组,包含1000个等间隔点,每个点间隔为0.001秒。 - 信号计算:
np.sin(2 * np.pi * f * t)实现了公式s(t) = sin(2pi*f*t),NumPy的广播机制自动处理数组运算。 - 输出:代码打印信号的前10个点,便于验证。
import numpy as np # 定义信号参数 A = 1.0 # 振幅 f = 5 # 频率(Hz) fs = 1000 # 采样频率(Hz) T = 1 # 持续时间(秒) # 创建时间轴数组:从0到T,共fs*T个点 t = np.linspace(0, T, int(fs * T)) # 生成正弦波信号 signal = A * np.sin(2 * np.pi * f * t) # 打印前10个点示例 print("信号前10个点:", signal[:10])