NumPy 介绍:高效处理数组的 Python 库
在数据科学和数值计算领域,Python 已经成为不可或缺的工具。然而,标准的 Python 列表在处理大量数值数据时,效率往往不尽如人意。为了解决这一痛点,NumPy(Numerical Python 的缩写)应运而生。NumPy 是 Python 中用于科学计算的核心库,它提供了一个强大的 N 维数组对象,以及用于处理这些数组的各种工具。
1. 什么是 NumPy?
NumPy 是一个开源的 Python 库,专门设计用于在 Python 中进行高效的数值运算。它的核心是 ndarray 对象,这是一个多维数组,能够存储同类型的数据。NumPy 提供了一系列高级数学函数来操作这些数组,包括线性代数、傅里叶变换以及随机数生成等。
2. 为什么选择 NumPy?
Python 内置的列表(list)非常灵活,可以存储不同类型的数据。但这种灵活性也带来了性能上的牺牲。当处理数百万甚至数十亿的数字时,Python 列表的迭代和计算速度会变得非常慢。NumPy 的优势在于:
- 性能卓越: NumPy 的底层实现是用 C 和 Fortran 编写的,这使得它在执行数值计算时比纯 Python 快得多。它针对内存使用进行了优化,减少了数据在内存中的碎片化。
- 内存效率:
ndarray存储的是同类型数据,因此内存布局是连续的,这比 Python 列表(存储的是指向对象的指针)更加紧凑和高效。 - 强大的功能: NumPy 提供了大量的数学函数和操作,能够轻松完成向量化运算,避免了显式的循环,使得代码更简洁、更易读。
- 生态系统基石: 许多流行的数据科学库,如 Pandas、SciPy、Matplotlib、Scikit-learn 和 TensorFlow,都将 NumPy 数组作为其核心数据结构。学习 NumPy 是掌握这些库的基础。
3. ndarray 对象:NumPy 的核心
ndarray(N-dimensional array)是 NumPy 最核心的数据结构。它是一个同构(所有元素类型相同)的多维表格,用于存储数字数据。
ndarray 的主要属性:
ndim: 数组的维度(轴的数量)。shape: 一个元组,表示数组在每个维度上的大小。例如,一个 2×3 的矩阵的shape是(2, 3)。size: 数组中元素的总数量。dtype: 数组中元素的类型。NumPy 支持多种数据类型,如int8,int16,int32,int64,float16,float32,float64,complex64,bool等。itemsize: 数组中每个元素占用字节的大小。data: 包含实际数组元素的缓冲区。
示例:
“`python
import numpy as np
创建一个一维数组
arr1 = np.array([1, 2, 3, 4, 5])
print(“arr1:”, arr1)
print(“ndim:”, arr1.ndim) # 1
print(“shape:”, arr1.shape) # (5,)
print(“size:”, arr1.size) # 5
print(“dtype:”, arr1.dtype) # int64
创建一个二维数组 (矩阵)
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(“\narr2:\n”, arr2)
print(“ndim:”, arr2.ndim) # 2
print(“shape:”, arr2.shape) # (2, 3)
print(“size:”, arr2.size) # 6
print(“dtype:”, arr2.dtype) # int64
“`
4. 创建 NumPy 数组
NumPy 提供了多种便捷的方式来创建数组:
-
从 Python 列表或元组创建:
“`python
list_data = [1, 2, 3, 4]
arr_from_list = np.array(list_data)tuple_data = (5, 6, 7)
arr_from_tuple = np.array(tuple_data, dtype=float) # 指定数据类型
“` -
使用内置函数创建特定数组:
“`python
全零数组
zeros_arr = np.zeros((3, 4)) # 3行4列的零矩阵
全一数组
ones_arr = np.ones((2, 2), dtype=int) # 2×2的整数一矩阵
空数组(内容随机,取决于内存)
empty_arr = np.empty((2, 3))
单位矩阵
identity_matrix = np.eye(3) # 3×3的单位矩阵
对角矩阵
diag_matrix = np.diag([1, 2, 3])
“` -
创建等差数列或等比数列:
“`python
arange: 类似 range() 函数
arr_range = np.arange(0, 10, 2) # 从0到10(不包含),步长为2 -> [0, 2, 4, 6, 8]
linspace: 创建指定数量的等间隔数字
arr_linspace = np.linspace(0, 1, 5) # 从0到1(包含),生成5个数字 -> [0., 0.25, 0.5, 0.75, 1.]
“`
5. 基本数组操作
NumPy 数组支持非常直观和高效的元素级(element-wise)操作。
-
算术运算: 加、减、乘、除、幂等操作都是作用于数组的每个对应元素。
“`python
a = np.array([10, 20, 30, 40])
b = np.array([1, 2, 3, 4])print(“a + b =”, a + b) # [11, 22, 33, 44]
print(“a – b =”, a – b) # [9, 18, 27, 36]
print(“a * b =”, a * b) # [10, 40, 90, 160] (元素级乘法,不是矩阵乘法)
print(“a / b =”, a / b) # [10., 10., 10., 10.]
print(“b ** 2 =”, b ** 2) # [1, 4, 9, 16]
“` -
比较运算: 返回一个布尔数组。
python
print("a > 20 =", a > 20) # [False False True True] -
通用函数 (ufunc): NumPy 提供了大量的数学函数,可以对数组的每个元素进行操作。
python
arr = np.array([0, np.pi/2, np.pi])
print("sin(arr) =", np.sin(arr)) # [0. 1. 0.] (近似值)
print("sqrt(arr) =", np.sqrt(arr))
print("exp(arr) =", np.exp(arr)) -
聚合函数: 用于对数组进行统计计算。
“`python
matrix = np.array([[1, 2, 3], [4, 5, 6]])
print(“Sum of all elements:”, matrix.sum()) # 21
print(“Min element:”, matrix.min()) # 1
print(“Max element:”, matrix.max()) # 6沿指定轴求和 (axis=0 代表列,axis=1 代表行)
print(“Sum along columns (axis=0):”, matrix.sum(axis=0)) # [5, 7, 9] (1+4, 2+5, 3+6)
print(“Sum along rows (axis=1):”, matrix.sum(axis=1)) # [6, 15] (1+2+3, 4+5+6)
“` -
广播 (Broadcasting): NumPy 的一个强大特性,它允许不同形状的数组在特定条件下进行算术运算。简单来说,较小的数组会被“广播”到较大数组的形状,以便它们兼容。
“`python
arr_broadcast = np.array([[1, 2, 3], [4, 5, 6]])
scalar = 10
print(“arr_broadcast + scalar:\n”, arr_broadcast + scalar)输出:
[[11 12 13]
[14 15 16]]
“`
6. 索引和切片
NumPy 数组的索引和切片方式与 Python 列表类似,但更加强大,尤其是在多维数组中。
-
基本索引:
“`python
arr = np.array([10, 20, 30, 40, 50])
print(arr[0]) # 10
print(arr[-1]) # 50matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix[0, 0]) # 1 (第一行第一列)
print(matrix[1, 2]) # 6 (第二行第三列)
“` -
切片:
start:end:step“`python
print(arr[1:4]) # [20 30 40]
print(arr[::2]) # [10 30 50] (每隔一个元素)二维数组切片
print(“Row 1:”, matrix[1, :]) # [4 5 6] (第二行所有列)
print(“Col 2:”, matrix[:, 1]) # [2 5 8] (所有行第二列)
print(“Sub-matrix:\n”, matrix[0:2, 0:2])输出:
[[1 2]
[4 5]]
“`
-
布尔索引: 使用布尔数组来选择元素。
python
data = np.array([1, 5, 2, 8, 3, 9, 4])
mask = (data > 3)
print("Mask:", mask) # [False True False True False True True]
print("Elements > 3:", data[mask]) # [5 8 9 4] -
花式索引 (Fancy Indexing): 使用整数数组作为索引来选择任意的行或列。
“`python
arr_fancy = np.arange(10, 100, 10).reshape(3, 3)
print(“Original array:\n”, arr_fancy)输出:
[[10 20 30]
[40 50 60]
[70 80 90]]
选择特定的行和列
print(“Fancy indexed:\n”, arr_fancy[[0, 2], [1, 0]]) # 选择 (0,1) 和 (2,0) 处的元素 -> [20 70]
“`
7. 数组形状操作
改变数组的形状而不改变其数据。
-
reshape(): 改变数组的形状。新形状的元素总数必须与原数组相同。“`python
arr_flat = np.arange(12) # [0, 1, …, 11]
arr_reshaped = arr_flat.reshape((3, 4)) # 3行4列矩阵
print(arr_reshaped)arr_reshaped_auto = arr_flat.reshape(2, -1) # -1 表示该维度自动计算
print(arr_reshaped_auto)
“` -
flatten()和ravel(): 将多维数组转换为一维数组。python
matrix = np.array([[1, 2, 3], [4, 5, 6]])
print(matrix.flatten()) # [1 2 3 4 5 6] (返回副本)
print(matrix.ravel()) # [1 2 3 4 5 6] (返回视图,可能共享内存)
8. 总结
NumPy 是 Python 进行科学计算的基石。通过其高效的 ndarray 对象和丰富的操作函数,它极大地提升了 Python 在处理数值数据时的性能和便捷性。无论是进行简单的数据统计、复杂的线性代数运算,还是为机器学习模型准备数据,NumPy 都是数据科学家和工程师不可或缺的工具。掌握 NumPy 不仅能让你的 Python 数值计算代码更快、更简洁,更是进入更广阔的数据科学世界的通行证。