NumPy(Numerical Python)是Python科学计算的基础库,提供了高性能的多维数组对象和大量数学函数。作为数据科学和机器学习领域的核心工具,掌握NumPy是每个Python开发者的必备技能。本文将带你全面了解NumPy的核心功能,并通过丰富案例展示其强大能力。
一、NumPy简介与安装
NumPy的核心是ndarray
(N-dimensional array)对象,这是一个快速、灵活的大数据容器,允许你在Python中进行向量化运算,避免了低效的循环操作。
安装NumPy非常简单:
pip install numpy
导入惯例:
import numpy as np
二、NumPy基础:数组创建与操作
案例1:创建数组的多种方式
# 从列表创建
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1) # 输出: [1 2 3 4 5]
# 创建全零数组
zeros = np.zeros((3, 3))
print(zeros)
# 输出:
# [[0. 0. 0.]
# [0. 0. 0.]
# [0. 0. 0.]]
# 创建全1数组
ones = np.ones((2, 4))
print(ones)
# 输出:
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]]
# 创建等差数列
range_arr = np.arange(0, 10, 2) # 从0开始,到10结束(不含),步长为2
print(range_arr) # 输出: [0 2 4 6 8]
# 创建等间隔数组
linspace_arr = np.linspace(0, 1, 5) # 0到1之间均匀分布的5个数
print(linspace_arr) # 输出: [0. 0.25 0.5 0.75 1. ]
# 创建随机数组
random_arr = np.random.rand(3, 2) # 3行2列的随机数组(0-1之间)
print(random_arr)
# 输出示例:
# [[0.5488135 0.71518937]
# [0.60276338 0.54488318]
# [0.4236548 0.64589411]]
案例2:数组的基本属性
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("数组形状:", arr.shape) # 输出: (2, 3)
print("数组维度:", arr.ndim) # 输出: 2
print("数组元素总数:", arr.size) # 输出: 6
print("数组数据类型:", arr.dtype) # 输出: int64
三、NumPy核心功能
案例3:数组索引与切片
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 获取单个元素
print(arr[1, 2]) # 输出: 6 (第二行第三列)
# 切片获取子数组
print(arr[:2, 1:]) # 前两行,第二列到最后一列
# 输出:
# [[2 3]
# [5 6]]
# 布尔索引
mask = arr > 5
print(mask)
# 输出:
# [[False False False]
# [False False True]
# [ True True True]]
print(arr[mask]) # 输出: [6 7 8 9]
# 花式索引
print(arr[[0, 2], [0, 1]]) # 获取(0,0)和(2,1)位置的元素
# 输出: [1 8]
案例4:数组运算
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(np.sin(a)) # 输出: [0.84147098 0.90929743 0.14112001]
# 矩阵乘法
matrix_a = np.array([[1, 2], [3, 4]])
matrix_b = np.array([[5, 6], [7, 8]])
print(np.dot(matrix_a, matrix_b))
# 输出:
# [[19 22]
# [43 50]]
# 统计运算
data = np.array([[1, 2], [3, 4], [5, 6]])
print("平均值:", np.mean(data)) # 输出: 3.5
print("列平均值:", np.mean(data, axis=0)) # 输出: [3. 4.]
print("行平均值:", np.mean(data, axis=1)) # 输出: [1.5 3.5 5.5]
print("总和:", np.sum(data)) # 输出: 21
print("最大值:", np.max(data)) # 输出: 6
print("最小值位置:", np.argmin(data)) # 输出: 0
案例5:数组形状操作
arr = np.arange(1, 10) # [1 2 3 4 5 6 7 8 9]
# 改变形状
reshaped = arr.reshape(3, 3)
print(reshaped)
# 输出:
# [[1 2 3]
# [4 5 6]
# [7 8 9]]
# 展平数组
flattened = reshaped.flatten()
print(flattened) # 输出: [1 2 3 4 5 6 7 8 9]
# 转置
transposed = reshaped.T
print(transposed)
# 输出:
# [[1 4 7]
# [2 5 8]
# [3 6 9]]
# 堆叠数组
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.vstack((a, b))) # 垂直堆叠
# 输出:
# [[1 2 3]
# [4 5 6]]
print(np.hstack((a, b))) # 水平堆叠
# 输出: [1 2 3 4 5 6]
四、NumPy高级应用
案例6:广播机制
广播是NumPy对不同形状数组进行算术运算的方式。
# 标量与数组运算
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr + 10)
# 输出:
# [[11 12 13]
# [14 15 16]]
# 不同形状数组运算
a = np.array([[1], [2], [3]]) # 形状(3,1)
b = np.array([10, 20, 30]) # 形状(3,)
print(a + b)
# 输出:
# [[11 21 31]
# [12 22 32]
# [13 23 33]]
# 更复杂的广播
matrix = np.ones((3, 3))
row = np.array([1, 2, 3])
print(matrix + row)
# 输出:
# [[2. 3. 4.]
# [2. 3. 4.]
# [2. 3. 4.]]
案例7:文件IO操作
# 保存和加载数组
arr = np.arange(10)
np.save('my_array.npy', arr) # 保存为.npy文件
loaded_arr = np.load('my_array.npy')
print(loaded_arr) # 输出: [0 1 2 3 4 5 6 7 8 9]
# 文本文件操作
data = np.array([[1.2, 3.4, 5.6], [7.8, 9.0, 1.1]])
np.savetxt('data.txt', data, delimiter=',') # 保存为CSV
loaded_data = np.loadtxt('data.txt', delimiter=',')
print(loaded_data)
# 输出:
# [[1.2 3.4 5.6]
# [7.8 9. 1.1]]
案例8:实用函数应用
# 多项式拟合
x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([0, 0.8, 0.9, 0.1, -0.8, -1.0])
coefficients = np.polyfit(x, y, 3) # 3次多项式拟合
print(coefficients) # 输出: [ 0.08703704 -0.81349206 1.69312169 -0.03968254]
# 线性代数
A = np.array([[1, 2], [3, 4]])
print("行列式:", np.linalg.det(A)) # 输出: -2.0
print("逆矩阵:\n", np.linalg.inv(A))
# 输出:
# [[-2. 1. ]
# [ 1.5 -0.5]]
# 随机数生成
normal_dist = np.random.normal(0, 1, 1000) # 均值为0,标准差为1的正态分布
print("均值:", np.mean(normal_dist)) # 接近0
print("标准差:", np.std(normal_dist)) # 接近1
# 唯一值与计数
data = np.array([1, 2, 2, 3, 3, 3, 4])
unique_values, counts = np.unique(data, return_counts=True)
print("唯一值:", unique_values) # 输出: [1 2 3 4]
print("计数:", counts) # 输出: [1 2 3 1]
五、NumPy性能优势
NumPy之所以快,主要因为:
- 连续内存存储
- 向量化操作避免了Python循环
- 底层用C实现
性能对比示例:
import time
# Python列表求和
py_list = list(range(1000000))
start = time.time()
sum(py_list)
print("Python列表耗时:", time.time() - start)
# NumPy数组求和
np_array = np.arange(1000000)
start = time.time()
np.sum(np_array)
print("NumPy数组耗时:", time.time() - start)
在我的测试中,NumPy版本比纯Python版本快约50倍!
六、总结与最佳实践
NumPy是Python科学计算生态系统的基石,掌握它能让你:
- 高效处理数值数据
- 实现复杂的数学运算
- 为机器学习/深度学习准备数据
最佳实践建议:
- 尽量使用向量化操作而非循环
- 合理利用广播机制
- 选择适当的数据类型节省内存
- 对大数组优先使用NumPy内置函数
希望通过本文的8个实用案例,你能全面掌握NumPy的核心功能,并在实际项目中灵活运用。NumPy的强大功能远不止于此,建议继续探索其官方文档和更高级的应用场景。