Python数据处理:NumPy数值计算实操教程(新手到进阶)
·
文章目录
NumPy是Python数值计算的“基石库”——它以C语言级别的效率处理数组/矩阵运算,是Pandas、Matplotlib、Scikit-learn等数据分析库的底层依赖。不管是批量数值计算、矩阵运算,还是数据预处理,掌握NumPy都能让你的代码运行效率提升百倍。本文从实际数据处理场景出发,详解NumPy的核心用法、性能优势和实战技巧,新手也能快速落地。
一、核心认知:为什么用NumPy?
Python原生列表(list)虽然灵活,但存在两大致命缺陷:
- 效率低:列表存储的是Python对象,运算时需逐一遍历,CPU密集型任务速度慢;
- 功能弱:无原生的矩阵运算、广播机制,需手动实现复杂数值计算。
NumPy的核心优势:
- 高性能:基于连续内存的数组(ndarray)存储,运算由C语言实现,避开Python解释器开销;
- 向量化:支持“整组运算”(无需循环),代码更简洁;
- 丰富接口:内置矩阵、线性代数、随机数等数值计算功能;
- 内存高效:ndarray比列表节省80%以上内存(如存储100万浮点数,列表占≈8MB,NumPy占≈4MB)。
快速上手:安装与基础导入
# 安装NumPy
pip install numpy
# 导入并简写(行业通用规范)
import numpy as np
二、NumPy核心:ndarray数组(基础中的基础)
ndarray(N-dimensional array)是NumPy的核心数据结构,代表“多维数组”,所有数值计算都围绕它展开。
1. 创建ndarray数组(常用方式)
| 创建方式 | 代码示例 | 适用场景 |
|---|---|---|
| 从列表/元组创建 | np.array([1,2,3]) | 手动输入少量数据 |
| 全0数组 | np.zeros((3,4)) | 初始化矩阵、占位符 |
| 全1数组 | np.ones((2,3)) | 初始化权重、基准值 |
| 空数组(随机值) | np.empty((2,2)) | 快速创建大数组(需后续赋值) |
| 范围数组 | np.arange(0,10,2) | 生成连续/步长数值 |
| 等距数组 | np.linspace(0,1,5) | 生成指定数量的等距值 |
| 随机数组 | np.random.rand(3,3) | 模拟数据、随机初始化 |
实战示例:
# 1. 一维数组
arr1 = np.array([1, 2, 3, 4, 5])
print("一维数组:", arr1) # 输出:[1 2 3 4 5]
# 2. 二维数组(矩阵)
arr2 = np.array([[1,2,3], [4,5,6]])
print("二维数组形状:", arr2.shape) # 输出:(2, 3)(2行3列)
print("数组维度:", arr2.ndim) # 输出:2(二维)
print("数据类型:", arr2.dtype) # 输出:int64(可指定dtype=np.float32)
# 3. 生成范围数组
arr3 = np.arange(0, 10, 2) # 0到10,步长2
print("范围数组:", arr3) # 输出:[0 2 4 6 8]
# 4. 随机数组(0-1之间的浮点数)
arr4 = np.random.rand(3, 3)
print("随机数组:\n", arr4)
2. 数组索引与切片(数据提取核心)
NumPy的索引/切片与Python列表类似,但支持“多维索引”,是提取子数组的关键。
(1)一维数组索引/切片
arr = np.arange(10)
print(arr[5]) # 索引:取第5个元素 → 5
print(arr[3:8]) # 切片:3到7(左闭右开)→ [3 4 5 6 7]
print(arr[::2]) # 步长切片:每隔1个取1个 → [0 2 4 6 8]
(2)二维数组索引/切片(行+列)
arr = np.array([[1,2,3], [4,5,6], [7,8,9]])
print(arr[1, 2]) # 取第1行第2列 → 6
print(arr[0:2, :]) # 取前2行,所有列 → [[1 2 3], [4 5 6]]
print(arr[:, 1]) # 取所有行,第1列 → [2 5 8]
print(arr[1:, 1:]) # 取第1行及以后,第1列及以后 → [[5 6], [8 9]]
(3)布尔索引(条件筛选)
arr = np.random.randint(0, 20, (3,3))
print("原始数组:\n", arr)
# 筛选大于10的元素
mask = arr > 10
print("大于10的元素:\n", arr[mask])
3. 数组形状操作(重塑/合并/拆分)
(1)重塑数组(reshape)
arr = np.arange(12)
arr_3x4 = arr.reshape(3, 4) # 转为3行4列
print("3x4数组:\n", arr_3x4)
arr_flat = arr_3x4.flatten() # 展平为一维
print("展平数组:", arr_flat)
(2)合并数组(concatenate/vstack/hstack)
arr1 = np.array([[1,2], [3,4]])
arr2 = np.array([[5,6], [7,8]])
# 垂直合并(行增加)
v_arr = np.vstack((arr1, arr2))
print("垂直合并:\n", v_arr)
# 水平合并(列增加)
h_arr = np.hstack((arr1, arr2))
print("水平合并:\n", h_arr)
(3)拆分数组(split)
arr = np.arange(12).reshape(3,4)
# 按行拆分为2部分
split_arr = np.split(arr, 3, axis=0)
print("按行拆分:", split_arr)
三、NumPy核心运算:向量化计算(无需循环)
NumPy的“向量化运算”是效率提升的关键——直接对整个数组运算,替代Python循环,速度提升10~100倍。
1. 基础算术运算
arr1 = np.array([1,2,3])
arr2 = np.array([4,5,6])
print("加法:", arr1 + arr2) # [5 7 9]
print("减法:", arr1 - arr2) # [-3 -3 -3]
print("乘法:", arr1 * arr2) # [4 10 18](元素级乘法)
print("除法:", arr1 / arr2) # [0.25 0.4 0.5]
print("幂运算:", arr1 **2) # [1 4 9]
print("取模:", arr2 % arr1) # [0 1 0]
2. 矩阵运算(线性代数核心)
注意:*是元素级乘法,矩阵乘法需用@或np.dot()。
# 矩阵乘法(2x3 × 3x2 = 2x2)
arr1 = np.array([[1,2,3], [4,5,6]])
arr2 = np.array([[1,2], [3,4], [5,6]])
# 方法1:@运算符(Python3.5+)
mat_mul1 = arr1 @ arr2
# 方法2:np.dot()
mat_mul2 = np.dot(arr1, arr2)
print("矩阵乘法结果:\n", mat_mul1)
# 输出:
# [[22 28]
# [49 64]]
3. 聚合运算(统计分析)
| 聚合函数 | 功能 | 示例 |
|---|---|---|
np.sum() | 求和 | np.sum(arr) |
np.mean() | 均值 | np.mean(arr, axis=0)(按列求均值) |
np.max()/np.min() | 最大/最小值 | np.max(arr, axis=1)(按行求最大值) |
np.argmax()/np.argmin() | 最大/最小值索引 | np.argmax(arr) |
np.std()/np.var() | 标准差/方差 | np.std(arr) |
实战示例:
arr = np.array([[1,2,3], [4,5,6], [7,8,9]])
print("数组总和:", np.sum(arr)) # 45
print("按列求和:", np.sum(arr, axis=0)) # [12 15 18]
print("按行求均值:", np.mean(arr, axis=1)) # [2. 5. 8.]
print("数组最大值:", np.max(arr)) # 9
print("最大值索引:", np.argmax(arr)) # 8(一维索引)
4. 广播机制(不同形状数组运算)
NumPy的“广播”允许不同形状的数组进行运算,核心规则:
- 维度少的数组自动补维度(如一维→二维);
- 维度大小为1的轴自动扩展,匹配另一数组的维度。
实战示例:
# 示例1:标量与数组运算(广播到所有元素)
arr = np.array([[1,2], [3,4]])
print(arr + 10) # 所有元素+10 → [[11 12], [13 14]]
# 示例2:一维数组与二维数组运算
arr1 = np.array([[1,2,3], [4,5,6]])
arr2 = np.array([10, 20, 30])
print(arr1 + arr2) # arr2广播到每一行 → [[11 22 33], [14 25 36]]
# 示例3:维度为1的数组广播
arr1 = np.array([[1], [2], [3]]) # (3,1)
arr2 = np.array([10, 20]) # (2,)
print(arr1 + arr2) # 广播为(3,2) → [[11 21], [12 22], [13 23]]
四、NumPy实战案例:数据预处理(真实场景)
场景:清洗并分析一组传感器数据
import numpy as np
# 1. 生成模拟传感器数据(含异常值:-999代表缺失)
sensor_data = np.random.randint(0, 100, (100, 3)) # 100行3列,0-99
# 随机插入10个缺失值
np.put(sensor_data, np.random.choice(100*3, 10), -999)
# 2. 数据清洗:替换缺失值为均值
# 步骤1:筛选非缺失值
mask = sensor_data != -999
# 步骤2:按列计算均值(忽略缺失值)
col_means = np.mean(sensor_data[mask].reshape(-1, 3), axis=0)
# 步骤3:替换缺失值
sensor_data[sensor_data == -999] = np.take(col_means, np.where(sensor_data == -999)[1])
print("清洗后数据前5行:\n", sensor_data[:5])
# 3. 数据标准化((值-均值)/标准差)
data_mean = np.mean(sensor_data, axis=0)
data_std = np.std(sensor_data, axis=0)
normalized_data = (sensor_data - data_mean) / data_std
print("标准化后数据前5行:\n", normalized_data[:5])
# 4. 统计分析
print("各列均值:", np.mean(normalized_data, axis=0)) # 接近0
print("各列标准差:", np.std(normalized_data, axis=0)) # 接近1
print("整体最大值:", np.max(normalized_data))
print("整体最小值:", np.min(normalized_data))
五、NumPy性能优化:避开这些坑
1. 避免频繁创建数组
# 错误:循环内创建数组(慢)
arr_list = []
for i in range(10000):
arr_list.append(np.array([i]))
arr = np.concatenate(arr_list)
# 正确:先创建空数组,再赋值(快)
arr = np.empty(10000)
for i in range(10000):
arr[i] = i
2. 用向量化替代Python循环
# 示例:计算数组每个元素的平方
arr = np.arange(1000000)
# 慢:Python循环(≈0.1秒)
result1 = []
for x in arr:
result1.append(x**2)
# 快:NumPy向量化(≈0.001秒,快100倍)
result2 = arr **2
3. 指定合适的数据类型
NumPy默认用int64/float64,可根据需求缩小类型(如int32/float32),节省内存:
arr = np.array([1,2,3], dtype=np.int32) # 占用内存减半
arr = np.array([1.1, 2.2], dtype=np.float32)
4. 避免拷贝数组(用视图替代)
arr = np.arange(10)
arr_view = arr[:5] # 视图(不拷贝,修改会影响原数组)
arr_copy = arr[:5].copy() # 拷贝(独立内存)
六、NumPy进阶:线性代数与随机数
1. 线性代数(np.linalg)
# 矩阵求逆
mat = np.array([[1,2], [3,4]])
inv_mat = np.linalg.inv(mat)
print("矩阵逆:\n", inv_mat)
# 求解线性方程组 Ax = b
A = np.array([[1,2], [3,4]])
b = np.array([5, 11])
x = np.linalg.solve(A, b)
print("方程组解:", x) # [1. 2.]
# 特征值与特征向量
eigenvalues, eigenvectors = np.linalg.eig(mat)
print("特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)
2. 随机数生成(np.random)
# 生成指定范围的随机整数
rand_int = np.random.randint(0, 10, (3,3))
print("随机整数数组:\n", rand_int)
# 生成正态分布随机数(均值0,标准差1)
rand_norm = np.random.normal(0, 1, (3,3))
print("正态分布数组:\n", rand_norm)
# 随机打乱数组
arr = np.arange(10)
np.random.shuffle(arr)
print("打乱后数组:", arr)
更多推荐



所有评论(0)