目录
NumPy(Numerical Python)是 Python 中用于科学计算的核心库,它提供了高性能的多维数组对象以及一系列用于数组操作的工具。对于数据处理、机器学习、科学计算等领域,NumPy 都是不可或缺的基础。本文将结合实际代码示例,带你系统学习 NumPy 的核心功能。
一、NumPy 的安装与基础概念
安装 NumPy
使用 pip 命令即可快速安装 NumPy:
# 安装命令
pip install numpy
核心概念:数组(Array)
NumPy 的核心是数组(ndarray),它类似于 Python 的列表,但能更高效地存储和处理多维数据(矩阵)。与列表相比,数组的优势在于:
- 支持批量元素操作,无需循环
- 内存占用更小,计算速度更快
- 提供丰富的数学运算函数
二、数组的创建
1. 从列表创建数组
使用np.array()
函数可以将 Python 列表转换为 NumPy 数组,支持创建一维、二维、三维甚至更高维的数组:
import numpy as np
# 一维数组
list1 = [1, 2, 3, 4, 5]
v = np.array(list1)
print("一维数组:\n", v)
# 二维数组(由多个一维数组构成)
m = np.array([list1, list1, list1])
print("二维数组:\n", m)
# 三维数组(由多个二维数组构成)
z = np.array([m, m, m])
print("三维数组:\n", z)
2. 数组的基本属性
每个数组都有几个重要属性,用于描述其特征:
# 形状(行数和列数等)
print("形状:", m.shape) # 输出 (3, 5),表示3行5列
# 维度
print("维度:", m.ndim) # 输出 2,表示二维数组
# 元素总数
print("元素总数:", m.size) # 输出 15(3×5)
# 元素类型
print("元素类型:", m.dtype) # 输出 int64(默认整数类型)
3. 创建特殊数组
NumPy 提供了专门的函数创建具有特定特征的数组:
# 全0数组
zeros_arr = np.zeros((2, 2)) # 2×2的全0数组
print("全0数组:\n", zeros_arr)
# 全1数组
ones_arr = np.ones((3, 2)) # 3×2的全1数组
print("全1数组:\n", ones_arr)
# 填充指定值的数组
full_arr = np.full((2, 2, 2), 5) # 2×2×2的全5数组
print("指定值数组:\n", full_arr)
# 单位矩阵(对角线为1,其余为0)
eye_arr = np.eye(3) # 3×3的单位矩阵
print("单位矩阵:\n", eye_arr)
4. 生成规律序列
np.arange(start, end, step)
:生成指定步长的序列(左闭右开)np.linspace(start, end, nums)
:生成指定数量的等间隔序列(左右闭区间)
# 生成0到9,步长为3的序列
arange_arr = np.arange(0, 9, 3)
print("arange结果:", arange_arr) # 输出 [0 3 6]
# 生成0到1之间的21个等间隔数
linspace_arr = np.linspace(0, 1, 21)
print("linspace结果:", linspace_arr)
三、数组的维度操作
1. 升维(改变数组形状)
使用reshape(newshape)
方法可以改变数组的维度,-1
表示自动计算该维度的大小:
list1 = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8]
v = np.array(list1) # 一维数组(16个元素)
# 一维变二维:4行4列
r1 = v.reshape(4, 4)
print("一维变二维:\n", r1)
# 一维变三维:1个2×8的二维数组(-1自动计算为8)
r2 = v.reshape(1, -1, 2)
print("一维变三维:\n", r2)
# 二维变三维:2个2×4的二维数组
r3 = r1.reshape(2, 2, 4)
print("二维变三维:\n", r3)
另外,resize(newshape)
方法会直接修改原数组的维度(无返回值):
v.resize(4, 4) # 直接修改原数组为4×4
print("resize后的数组:\n", v)
2. 降维(将高维数组转为低维)
ravel()
:返回原数组的视图(修改可能影响原数组)flatten()
:返回原数组的副本(修改不影响原数组)- 直接修改
shape
属性
# 三维数组(2×2×2)
v = np.array([1,2,3,4,5,6,7,8]).reshape(2,2,2)
# 转为一维数组(视图)
r2 = v.ravel()
# 转为一维数组(副本)
r3 = v.flatten()
# 通过shape属性降维
v.shape = (1, 8) # 三维变二维(1×8)
print("修改shape后的数组:\n", v)
四、数组元素的选取与修改
1. 一维数组
通过索引、切片或列表批量选取元素,并支持直接修改:
array1 = np.arange(1, 9, 1) # [1 2 3 4 5 6 7 8]
# 选取单个元素(索引从0开始)
a = array1[1] # 取第2个元素,值为2
# 批量选取元素(通过列表指定索引)
b = array1[[1, 3, 5]] # 取索引1、3、5的元素,结果[2 4 6]
# 切片选取(左闭右开)
c = array1[0:6] # 取索引0到5的元素,结果[1 2 3 4 5 6]
# 修改元素
array1[0] = 10 # 单个修改
array1[[1, 3, 5]] = 20 # 批量修改
array1[0:6] = 100 # 切片修改
2. 二维数组
通过[行索引, 列索引]
选取,:
表示选取所有行或列:
array1 = np.arange(24).reshape(4, 6) # 4行6列的数组
# 选取单个元素(第2行第5列,索引从0开始)
a = array1[1, 4]
# 选取某行(第4行所有元素)
b = array1[3, :]
# 选取某些行(第1-2行,第1和3行)
c = array1[0:2, :] # 切片选取
d = array1[[0, 2], :] # 列表批量选取
# 选取某列(第4列所有元素)
e = array1[:, 3]
# 选取某些列(第1-3列,第1和4列)
f = array1[:, 0:3]
g = array1[:, [0, 3]]
# 修改元素(类似选取方式)
array1[1, 4] = 100 # 单个修改
array1[3, :] = 100 # 整行修改
3. 三维数组
三维数组可以理解为 “多个二维数组的集合”,选取方式为[二维数组索引, 行索引, 列索引]
:
array1 = np.arange(48).reshape(2, 4, 6) # 2个4行6列的二维数组
# 选取单个元素(第2个二维数组的第1行第1列)
a = array1[1, 0, 0]
# 选取某行(第1个二维数组的第2行所有元素)
b = array1[0, 1, :]
# 选取某列(第2个二维数组的所有行第2列)
e = array1[1, :, 1]
五、数组的运算
1. 元素级运算
数组的加减乘除等运算默认是对应元素的操作,无需循环:
array1 = np.arange(1, 5).reshape(2, 2) # [[1 2], [3 4]]
array2 = 2 * array1 # [[2 4], [6 8]]
# 加法
print("加法:\n", array1 + array2) # [[3 6], [9 12]]
# 减法
print("减法:\n", array1 - array2) # [[-1 -2], [-3 -4]]
# 乘法(元素级)
print("乘法:\n", array1 * array2) # [[2 8], [18 32]]
# 除法
print("除法:\n", array1 / array2) # [[0.5 0.5], [0.5 0.5]]
# 取余和取整
print("取余:\n", array1 % array2) # [[1 2], [3 4]]
print("取整:\n", array1 // array2) # [[0 0], [0 0]]
2. 矩阵运算
- 矩阵乘法(点乘):使用
dot()
方法或np.dot()
- 矩阵求逆:使用
np.linalg.inv()
(仅适用于方阵)
a = np.arange(4).reshape(2, 2) # [[0 1], [2 3]]
b = a.copy()
# 矩阵乘法(点乘)
a1 = a.dot(b) # 等价于 np.dot(a, b)
print("矩阵乘法:\n", a1) # [[2 3], [6 11]]
# 矩阵求逆(若存在)
a3 = np.linalg.inv(a) # 计算a的逆矩阵
六、数组的组合与切割
1. 数组组合
- 水平组合(按列拼接):
np.hstack()
或np.concatenate(..., axis=1)
- 垂直组合(按行拼接):
np.vstack()
或np.concatenate(..., axis=0)
array1 = np.arange(9).reshape(3, 3) # 3×3数组
array2 = 2 * array1 # 3×3数组
# 水平组合(列数增加)
h_combine = np.hstack((array1, array2))
# 等价于 np.concatenate((array1, array2), axis=1)
print("水平组合:\n", h_combine)
# 垂直组合(行数增加)
v_combine = np.vstack((array1, array2))
# 等价于 np.concatenate((array1, array2), axis=0)
print("垂直组合:\n", v_combine)
2. 数组切割
- 水平切割(按列分割):
np.hsplit()
或np.split(..., axis=1)
- 垂直切割(按行分割):
np.vsplit()
或np.split(..., axis=0)
- 强制切割(不等分):
np.array_split()
array1 = np.arange(16).reshape(4, 4) # 4×4数组
# 水平切割为2等份
h_split = np.hsplit(array1, 2)
# 等价于 np.split(array1, 2, axis=1)
print("水平切割:\n", h_split)
# 垂直切割为2等份
v_split = np.vsplit(array1, 2)
# 等价于 np.split(array1, 2, axis=0)
print("垂直切割:\n", v_split)
# 强制不等分切割(按列分为3份)
force_split = np.array_split(array1, 3, axis=1)
print("强制切割:\n", force_split)
七、随机数生成
NumPy 的random
模块提供了丰富的随机数生成函数,常用于模拟数据。
1. 基本随机整数
np.random.randint(start, end, size)
:生成指定范围的随机整数
np.random.seed(1000) # 设置随机种子,保证结果可复现
# 单个随机整数(0-10之间,左闭右开)
r1 = np.random.randint(0, 10)
# 随机整数矩阵(5×5)
r3 = np.random.randint(0, 10, size=(5, 5))
2. 随机浮点数
np.random.rand(size)
:生成 (0,1) 之间的随机浮点数np.random.normal(loc, scale, size)
:生成符合正态分布的浮点数(loc 为均值,scale 为标准差)
# (0,1)之间的随机浮点数(5×5矩阵)
r4 = np.random.rand(5, 5)
# 正态分布(均值5,标准差10,5×5矩阵)
r5 = np.random.normal(5, 10, size=(5, 5))
八、文件的加载与保存
NumPy 支持直接读写文本文件中的数组数据。
1. 从文本文件加载数据
np.loadtxt()
:加载文本文件,通过delimiter
指定分隔符
# 加载以制表符分隔的文本文件
data = np.loadtxt('datingTestSet2.txt', delimiter='\t')
print("加载的数据:\n", data)
2. 将数组保存到文本文件
np.savetxt()
:保存数组到文本文件
array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.savetxt('array.txt', array) # 保存到array.txt
九、常用统计函数
NumPy 提供了多种统计函数,用于快速计算数组的统计特征:
array1 = np.random.normal(size=(3, 3)) # 3×3的随机正态分布数组
# 方差
print("方差:", array1.var())
# 标准差
print("标准差:", array1.std())
# 均值
print("均值:", array1.mean())
# 总和
print("总和:", array1.sum())
# 中位数
print("中位数:", np.median(array1))
# 按行求和(axis=1)
print("行求和:", array1.sum(axis=1))
# 按列求和(axis=0)
print("列求和:", array1.sum(axis=0))
十、深拷贝与浅拷贝
数组的拷贝需要注意 “引用” 与 “副本” 的区别:
- 浅拷贝:直接赋值,两个变量指向同一数组(修改会相互影响)
- 深拷贝:使用
copy()
方法,创建新数组(修改互不影响)
array1 = np.array([1, 2, 3])
# 浅拷贝(引用)
array2 = array1
array2[0] = 100 # 修改array2,array1也会变
print("浅拷贝后array1:", array1) # [100 2 3]
# 深拷贝(副本)
array3 = array1.copy()
array3[0] = 10 # 修改array3,array1不变
print("深拷贝后array1:", array1) # [100 2 3]