NumPy是Python数值计算的“基石库”——它以C语言级别的效率处理数组/矩阵运算,是Pandas、Matplotlib、Scikit-learn等数据分析库的底层依赖。不管是批量数值计算、矩阵运算,还是数据预处理,掌握NumPy都能让你的代码运行效率提升百倍。本文从实际数据处理场景出发,详解NumPy的核心用法、性能优势和实战技巧,新手也能快速落地。

一、核心认知:为什么用NumPy?

Python原生列表(list)虽然灵活,但存在两大致命缺陷:

  1. 效率低:列表存储的是Python对象,运算时需逐一遍历,CPU密集型任务速度慢;
  2. 功能弱:无原生的矩阵运算、广播机制,需手动实现复杂数值计算。

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. 维度少的数组自动补维度(如一维→二维);
  2. 维度大小为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)
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐