NumPy库完全解析(从基础到进阶,附实战示例)

NumPy(Numerical Python)是Python科学计算的核心基础库 ,专为数值计算优化设计,提供了高性能的多维数组对象ndarray,以及配套的数组操作、数学计算、线性代数、随机数生成等功能。它解决了Python原生列表在数值计算中效率低、无向量化操作、缺乏数学工具的痛点,是Pandas、Matplotlib、Scikit-learn、TensorFlow等数据分析、可视化、机器学习库的底层依赖,掌握NumPy是Python数值计算和数据分析的必备基础。

本文将从安装、核心对象、基础操作、核心特性、常用函数、输入输出、实战最佳实践七个维度,全面讲解NumPy的所有核心知识点,所有示例均为可直接运行的极简代码,兼顾理解性和实用性。

一、NumPy安装与快速入门

1. 安装方式(pip/conda,二选一)

NumPy并非Python内置库,需手动安装,推荐使用以下命令:

bash 复制代码
# pip安装(通用,适合纯Python环境)
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple  # 国内源加速

# conda安装(适合Anaconda/Miniconda数据分析环境,自动解决依赖)
conda install numpy

2. 快速入门:Hello NumPy

通过简单示例感受NumPy与Python原生列表的区别,核心优势:向量化操作、无需循环、效率更高

python 复制代码
import numpy as np  # 导入NumPy,约定别名np(行业通用,必须遵守)

# 1. Python原生列表:计算每个元素的平方,需循环
python_list = [1, 2, 3, 4, 5]
list_square = [x ** 2 for x in python_list]
print("Python列表平方:", list_square)  # [1, 4, 9, 16, 25]

# 2. NumPy数组:直接向量化操作,无需循环
np_array = np.array([1, 2, 3, 4, 5])
np_square = np_array ** 2
print("NumPy数组平方:", np_square)  # [ 1  4  9 16 25]

# 3. 快速数学计算(求和、均值、标准差)
print("求和:", np_array.sum())    # 15
print("均值:", np_array.mean())  # 3.0
print("标准差:", np_array.std()) # 1.41421356

二、NumPy核心对象:ndarray多维数组

ndarray(N-dimensional array)是NumPy的核心数据结构 ,表示同构的多维数组(所有元素类型相同),这是其与Python原生列表(异构,可存不同类型数据)的核心区别,也是NumPy高效的关键原因。

1. ndarray的核心优势

  1. 同构存储:元素类型统一,内存连续分配,访问速度远快于原生列表;
  2. 向量化操作:直接对整个数组进行数学运算,无需显式循环,代码简洁且效率提升10~100倍;
  3. 多维支持:天然支持一维、二维、三维及更高维数组,完美适配矩阵、张量等数值计算场景;
  4. 丰富方法:内置大量数组操作、数学计算方法,无需手动实现;
  5. 低内存占用:相比原生列表,存储相同数据的内存占用大幅降低(如存储1000个整数,列表占用约8000字节,ndarray仅约4000字节)。

2. ndarray的创建方式(6种常用方式)

方式1:从Python原生数据结构转换(列表/元组)------最常用

通过np.array()将Python列表、元组(或嵌套列表/元组)转换为ndarray,自动推断元素类型。

python 复制代码
import numpy as np

# 一维数组:从列表转换
arr1d = np.array([1, 2, 3, 4, 5])
# 二维数组:从嵌套列表转换(矩阵,行×列)
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 三维数组:从三层嵌套列表转换(张量,页×行×列)
arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

print("一维数组:\n", arr1d, "\n维度:", arr1d.ndim)
print("二维数组:\n", arr2d, "\n维度:", arr2d.ndim)
print("三维数组:\n", arr3d, "\n维度:", arr3d.ndim)
方式2:创建固定值数组(全0/全1/空数组/指定值)

适用于初始化数组,指定形状即可,无需手动构造列表,常用在矩阵初始化、占位符场景。

python 复制代码
import numpy as np

# 全0数组:np.zeros(shape, dtype),shape为形状(整数/元组),dtype为数据类型
zeros_arr = np.zeros((2, 3), dtype=np.float32)  # 2行3列的全0浮点数组

# 全1数组:np.ones(shape, dtype)
ones_arr = np.ones(5, dtype=np.int64)  # 一维5个1的整数数组

# 空数组:np.empty(shape),初始化内存(值为随机垃圾值),比zeros/ones更快
empty_arr = np.empty((3, 2))

# 指定值数组:np.full(shape, fill_value),所有元素为fill_value
full_arr = np.full((2, 2), 99)  # 2行2列全为99的数组

print("全0数组:\n", zeros_arr)
print("全1数组:", ones_arr)
print("指定值数组:\n", full_arr)
方式3:创建有序数值数组(arange/linspace)

替代Python的range(),支持浮点数,可创建等步长/等份数的有序数组,适用于生成序列、坐标轴数据。

python 复制代码
import numpy as np

# np.arange(start, stop, step):左闭右开,步长可设为浮点数(区别于range)
arr_arange1 = np.arange(0, 10, 2)  # [0 2 4 6 8]
arr_arange2 = np.arange(5)         # 省略start,默认从0开始:[0 1 2 3 4]
arr_arange3 = np.arange(1.5, 5.5, 1.0)  # 浮点数步长:[1.5 2.5 3.5 4.5]

# np.linspace(start, stop, num):左闭右闭,生成num个等间距数值(重点)
arr_linspace = np.linspace(0, 1, 5)  # 0到1之间5个等间距数:[0.  0.25 0.5  0.75 1.  ]

# 拓展:logspace------生成等对数间距数组(适用于对数坐标)
arr_logspace = np.logspace(0, 2, 3)  # 10^0到10^2之间3个值:[  1.  10. 100.]

print("arange:", arr_arange1)
print("linspace:", arr_linspace)
方式4:创建随机数数组(np.random)------实战高频

NumPy的np.random模块提供了丰富的随机数生成功能,支持均匀分布、正态分布、整数随机等,适用于模拟数据、随机采样、机器学习初始化等场景。

python 复制代码
import numpy as np

# 1. 均匀分布:np.random.rand(shape) → [0,1)之间的随机浮点数
rand_arr = np.random.rand(2, 3)  # 2行3列均匀分布随机数

# 2. 标准正态分布:np.random.randn(shape) → 均值0,方差1的正态分布
randn_arr = np.random.randn(3, 2)  # 3行2列标准正态分布

# 3. 整数随机:np.random.randint(low, high, size) → [low,high)之间的随机整数
randint_arr = np.random.randint(0, 10, size=(2, 2))  # 2行2列0~9的随机整数

# 4. 固定随机种子:np.random.seed(n) → 保证随机数可复现(重要)
np.random.seed(42)  # 种子值任意,固定后每次运行生成的随机数相同
fixed_rand = np.random.rand(3)  # 固定结果:[0.37454012 0.95071431 0.73199394]

print("均匀分布随机数:\n", rand_arr)
print("随机整数:\n", randint_arr)
print("固定种子随机数:", fixed_rand)
方式5:创建单位矩阵/对角矩阵

适用于线性代数计算,单位矩阵(主对角线为1,其余为0)、对角矩阵(仅对角线有值)是线性代数的基础。

python 复制代码
import numpy as np

# 单位矩阵:np.eye(n, m=None) → n行m列,主对角线为1(m省略则为n阶方阵)
eye_arr = np.eye(3)  # 3阶单位矩阵
eye_arr2 = np.eye(2, 3)  # 2行3列单位矩阵

# 对角矩阵:np.diag(v) → v为列表/数组,生成以v为对角线的方阵
diag_arr = np.diag([1, 2, 3])  # 3阶对角矩阵,对角线为1,2,3

print("3阶单位矩阵:\n", eye_arr)
print("对角矩阵:\n", diag_arr)
方式6:从文件加载(后续第六部分详细讲解)

通过np.loadtxt()np.genfromtxt()加载文本文件(如csv、txt),np.load()加载NumPy专用格式文件(npy/npz),适用于实战中加载外部数据。

3. ndarray的核心属性(必记)

ndarray提供了6个核心属性,用于快速获取数组的基本信息,无需手动计算,是操作数组的基础。

python 复制代码
import numpy as np

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.float64)

# 1. ndim → 数组的维度(阶数)
print("维度:", arr.ndim)  # 2(二维数组)
# 2. shape → 数组的形状,返回元组:(行, 列, 页,...)
print("形状:", arr.shape)  # (2, 4) → 2行4列
# 3. size → 数组的总元素个数(shape各维度的乘积)
print("总元素数:", arr.size)  # 8
# 4. dtype → 数组的元素数据类型(NumPy专属类型,如np.int64、np.float32)
print("数据类型:", arr.dtype)  # float64
# 5. itemsize → 单个元素占用的字节数(如float64占8字节,int32占4字节)
print("单个元素字节数:", arr.itemsize)  # 8
# 6. nbytes → 数组占用的总字节数(size × itemsize)
print("总字节数:", arr.nbytes)  # 64

4. NumPy的常用数据类型(dtype)

NumPy提供了丰富的数值类型,核心是整数型、浮点型、布尔型 ,可通过dtype参数指定,或通过astype()转换,选择合适的类型能节省内存并提升效率

常用dtype对照表(重点掌握)
类型标识 描述 字节数 适用场景
np.int32 32位整数 4 常规整数计算(无大数值需求)
np.int64 64位整数 8 大数值整数计算(避免溢出)
np.float32 32位浮点 4 常规浮点计算(内存敏感场景)
np.float64 64位浮点 8 高精度浮点计算(默认,推荐)
np.bool_ 布尔型 1 条件判断、掩码筛选
np.str_ 字符串型 可变 存储字符串(尽量避免,用Pandas)
数据类型转换:astype()

astype()安全的类型转换方法,返回新数组(原数组不变),支持所有常用类型转换。

python 复制代码
import numpy as np

# 整数转浮点
arr_int = np.array([1, 2, 3])
arr_float = arr_int.astype(np.float64)
# 浮点转整数(直接截断小数部分,非四舍五入)
arr_float2 = np.array([1.9, 2.1, 3.5])
arr_int2 = arr_float2.astype(np.int32)
# 数值转布尔(0→False,非0→True)
arr_bool = arr_int.astype(np.bool_)

print("整数转浮点:", arr_float, arr_float.dtype)  # [1. 2. 3.] float64
print("浮点转整数:", arr_int2, arr_int2.dtype)    # [1 2 3] int32
print("数值转布尔:", arr_bool, arr_bool.dtype)    # [ True  True  True] bool_

三、ndarray基础操作(核心,实战高频)

1. 索引与切片:获取/修改数组元素

NumPy的索引与切片语法与Python原生列表高度相似 ,但支持多维索引 ,是获取数组子集、修改元素的核心操作,分为基础索引切片、花式索引、布尔索引三类,覆盖所有场景。

(1)基础索引切片(一维/二维/三维)
  • 一维数组:与Python列表完全一致,arr[start:stop:step](左闭右开);
  • 二维数组:arr[行索引, 列索引],行/列均可单独切片,逗号分隔;
  • 三维数组:arr[页索引, 行索引, 列索引],依次按维度切片。

核心特性 :基础切片返回的是原数组的视图(view),修改视图会同步修改原数组(节省内存,避免拷贝)。

python 复制代码
import numpy as np

# 一维数组切片
arr1d = np.arange(10)  # [0 1 2 3 4 5 6 7 8 9]
print("一维切片(2~8,步长2):", arr1d[2:9:2])  # [2 4 6 8]
print("一维逆序:", arr1d[::-1])  # [9 8 7 6 5 4 3 2 1 0]

# 二维数组切片(重点,矩阵操作)
arr2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print("取第2行:", arr2d[1])  # [5 6 7 8](行索引从0开始)
print("取第1列:", arr2d[:, 0])  # [1 5 9](:表示所有行)
print("取前2行,后2列:\n", arr2d[:2, 2:])  # [[3 4],[7 8]]
print("取第2行第3列元素:", arr2d[1, 2])  # 7(单个元素,标量)

# 视图特性:修改切片会改变原数组
slice_arr = arr2d[:2, :2]
slice_arr[:] = 0  # 切片所有元素设为0
print("修改视图后原数组:\n", arr2d)
# 结果:[[ 0  0  3  4],[ 0  0  7  8],[ 9 10 11 12]]
(2)花式索引(Fancy Indexing):整数数组索引

通过整数列表/数组 指定要获取的索引,适用于非连续、任意顺序 的元素获取,返回的是原数组的拷贝(修改不会影响原数组)。

python 复制代码
import numpy as np

arr1d = np.arange(10)
arr2d = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])

# 一维花式索引:取索引1、3、5的元素
print("一维花式索引:", arr1d[[1, 3, 5]])  # [1 3 5]

# 二维花式索引:取第0、2、3行,第1列的元素
print("二维花式索引:", arr2d[[0, 2, 3], 1])  # [2 6 8]
# 二维花式索引:取第1、3行,第0、1列(形成新矩阵)
print("二维花式索引(多行多列):\n", arr2d[[1, 3]][:, [0, 1]])  # [[3 4],[7 8]]
(3)布尔索引(Boolean Indexing):条件筛选

通过与原数组形状相同的布尔数组 筛选元素,适用于按条件过滤数据 (实战最常用,如筛选大于0、小于均值的元素),返回的是拷贝

python 复制代码
import numpy as np

arr = np.array([[1, -2, 3], [-4, 5, -6], [7, -8, 9]])
# 生成布尔数组:判断元素是否大于0
bool_arr = arr > 0
print("布尔数组:\n", bool_arr)

# 布尔索引:筛选所有大于0的元素(返回一维数组)
positive_arr = arr[bool_arr]
print("大于0的元素:", positive_arr)  # [1 3 5 7 9]

# 直接简写(实战常用):一行完成条件筛选
negative_arr = arr[arr < 0]
print("小于0的元素:", negative_arr)  # [-2 -4 -6 -8]

# 多条件筛选:用&(且)、|(或)、~(非),条件需加括号
cond_arr = arr[(arr > 0) & (arr < 8)]
print("大于0且小于8的元素:", cond_arr)  # [1 3 5 7]

2. 形状操作:修改数组的维度/形状

实战中常需根据需求修改数组形状(如将一维数组转为二维矩阵、将三维张量展平为一维),NumPy提供了5种核心形状操作方法,均不改变原数组 (除resize),返回新数组/视图。

方法 核心作用 关键特性 适用场景
reshape() 改变数组形状 返回视图,支持-1(自动计算维度) 任意形状转换(推荐)
flatten() 展平为一维数组 返回拷贝,修改不影响原数组 需独立展平数组时
ravel() 展平为一维数组 返回视图,修改影响原数组 仅展平,无需独立数组时(高效)
transpose()/T 数组转置 返回视图,二维用T更简洁 矩阵转置、维度交换
resize() 原地修改形状 无返回值,直接修改原数组 需覆盖原数组形状时

核心技巧reshape()中的-1表示自动计算该维度的大小(根据总元素数和其他维度),是实战中最常用的简化写法。

python 复制代码
import numpy as np

arr = np.arange(12)  # 一维数组:[0 1 2 ... 11],size=12

# 1. reshape:一维转二维(3行4列)
arr2d = arr.reshape(3, 4)
# reshape用-1:自动计算行(总元素12/列4=3行)
arr2d_1 = arr.reshape(-1, 4)
# 一维转三维(2页×3行×2列),-1自动计算列
arr3d = arr.reshape(2, 3, -1)

print("一维转二维:\n", arr2d)
print("三维数组形状:", arr3d.shape)  # (2, 3, 2)

# 2. 展平数组:flatten(拷贝)vs ravel(视图)
flat_arr = arr2d.flatten()
ravel_arr = arr2d.ravel()
flat_arr[0] = 99  # 修改拷贝,原数组不变
ravel_arr[1] = 88  # 修改视图,原数组同步改变
print("修改视图后原二维数组:\n", arr2d)

# 3. 转置:二维数组用T(简洁),高维用transpose
arr2d_T = arr2d.T  # 二维转置:4行3列
arr3d_T = arr3d.transpose(1, 0, 2)  # 三维转置:交换0和1维度
print("二维数组转置:\n", arr2d_T)

# 4. resize:原地修改(无返回值)
arr.resize(4, 3)
print("原地修改形状后:\n", arr)

3. 数组的拼接与分割

(1)数组拼接:将多个数组合并为一个

NumPy提供了通用拼接 np.concatenate()简化拼接 np.vstack()/np.hstack(),核心是指定拼接轴(axis)

  • axis=0垂直拼接(按行),要求数组列数相同(二维);
  • axis=1水平拼接(按列),要求数组行数相同(二维);
  • 一维数组默认按axis=0拼接。
python 复制代码
import numpy as np

# 二维数组准备
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])

# 1. 通用拼接:np.concatenate([arr1, arr2], axis=0/1)
v_concat = np.concatenate([arr1, arr2], axis=0)  # 垂直拼接
h_concat = np.concatenate([arr1, arr2], axis=1)  # 水平拼接

# 2. 简化拼接:vstack(垂直)、hstack(水平)(推荐,无需记axis)
v_stack = np.vstack([arr1, arr2])
h_stack = np.hstack([arr1, arr2])

print("垂直拼接:\n", v_stack)
print("水平拼接:\n", h_stack)

# 一维数组拼接
arr3 = np.array([1, 2])
arr4 = np.array([3, 4])
print("一维拼接:", np.hstack([arr3, arr4]))  # [1 2 3 4]
(2)数组分割:将一个数组拆分为多个

与拼接对应,提供通用分割 np.split()简化分割 np.vsplit()/np.hsplit(),指定分割轴分割点即可。

python 复制代码
import numpy as np

arr = np.arange(12).reshape(4, 3)  # 4行3列数组
# 1. 通用分割:np.split(arr, 分割数/分割点, axis=0/1)
arr_list1 = np.split(arr, 2, axis=0)  # 垂直分割为2个数组(各2行)
arr_list2 = np.split(arr, [1, 3], axis=1)  # 水平分割,在第1、3列处分割

# 2. 简化分割:vsplit(垂直)、hsplit(水平)
v_split = np.vsplit(arr, 2)
h_split = np.hsplit(arr, 3)  # 水平分割为3个数组(各1列)

print("垂直分割为2个:\n", arr_list1[0], "\n", arr_list1[1])
print("水平分割为3个:", h_split)

4. 数组的复制:视图(view)vs 拷贝(copy)

NumPy中数组的"复制"分为视图拷贝,这是极易混淆的点,直接影响内存使用和数据修改,必须明确区分:

(1)视图(View)------浅拷贝
  • 定义:仅复制数组的元数据(形状、维度、dtype),不复制实际数据,数据与原数组共享同一块内存;
  • 特性:修改视图会同步修改原数组,创建视图速度快、内存占用低;
  • 产生场景:基础切片、ravel()transpose()/Treshape()(大部分情况)。
(2)拷贝(Copy)------深拷贝
  • 定义:完全复制数组的元数据和实际数据,创建新的内存空间,与原数组完全独立;
  • 特性:修改拷贝不会影响原数组,创建拷贝速度慢、内存占用高;
  • 产生场景:花式索引、布尔索引、flatten()arr.copy()(显式拷贝,推荐)、数组运算。
示例:视图与拷贝的区别
python 复制代码
import numpy as np

arr = np.array([1, 2, 3, 4])
# 1. 视图:基础切片
view_arr = arr[1:3]
view_arr[:] = 99  # 修改视图
print("修改视图后原数组:", arr)  # [ 1 99 99  4](同步修改)

# 2. 拷贝:显式copy()
copy_arr = arr.copy()
copy_arr[:] = 0  # 修改拷贝
print("修改拷贝后原数组:", arr)  # [ 1 99 99  4](无影响)

# 3. 拷贝:布尔索引
bool_copy = arr[arr > 50]
bool_copy[:] = 100
print("布尔索引拷贝修改后原数组:", arr)  # [ 1 99 99  4](无影响)

实战建议 :若需独立使用数组子集,显式调用arr.copy() 创建拷贝,避免因视图修改导致原数组数据混乱。

四、NumPy核心特性:向量化操作与广播机制

这是NumPy高效的核心根源,也是与Python原生列表的本质区别,掌握这两个特性,才能真正写出简洁、高效的NumPy代码。

1. 向量化操作(Vectorization)

定义

无需显式编写for循环,直接对整个数组进行数学运算(加减乘除、幂运算、三角函数等),NumPy会自动将运算应用到每个元素上,这种操作称为向量化操作。

核心优势
  1. 代码简洁:省去循环代码,一行完成批量运算;
  2. 效率极高 :向量化操作由C语言底层实现,比Python原生循环快10~100倍(数据量越大,优势越明显);
  3. 支持所有数学运算:算术运算、比较运算、数学函数均支持向量化。
示例:向量化操作vs Python原生循环
python 复制代码
import numpy as np
import time

# 生成大数组(100万个元素),模拟实战场景
np_arr = np.arange(10**6)
py_list = list(range(10**6))

# 1. NumPy向量化操作:计算平方
start = time.time()
np_square = np_arr ** 2
print("向量化操作耗时:", time.time() - start, "秒")  # 约0.001秒

# 2. Python原生循环:计算平方
start = time.time()
py_square = [x ** 2 for x in py_list]
print("原生循环耗时:", time.time() - start, "秒")  # 约0.1秒(慢100倍)

# 其他向量化操作示例
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]
print("比较运算:", a > 2)  # [False False  True]

2. 广播机制(Broadcasting)

定义

当对形状不同的数组进行向量化操作时,NumPy会自动扩展数组的形状,使它们满足"可广播"条件,然后进行元素级运算,这种自动扩展机制称为广播。

核心价值

无需手动扩展数组形状(避免不必要的数据拷贝),即可对不同形状的数组进行运算,进一步简化代码并提升效率。

广播的3条核心规则(必须遵守,否则报错)

NumPy会从后往前逐维度比较两个数组的形状,只有满足以下规则,才能进行广播:

  1. 维度相同:两个数组的对应维度大小相同;
  2. 其中一个维度为1:若对应维度大小不同,其中一个必须为1,NumPy会将该维度扩展为另一个数组的维度大小;
  3. 维度缺失 :若一个数组的维度数少于另一个,自动在其前面补1,再按规则1、2判断。

简单记:从后比,要么相等,要么有一个是1。

常见广播示例(实战高频)
python 复制代码
import numpy as np

# 示例1:标量与数组广播(最常用)
a = np.array([1, 2, 3])
b = 2
print(a + b)  # [3 4 5] → 标量b被广播为[2,2,3]?不,[2,2,2]

# 示例2:一维数组与二维数组广播
a = np.array([[1, 2, 3], [4, 5, 6]])  # (2,3)
b = np.array([10, 20, 30])            # (3,) → 补1为(1,3) → 广播为(2,3)
print(a + b)  # [[11 22 33],[14 25 36]]

# 示例3:两个数组均需广播
a = np.array([[1], [2], [3]])  # (3,1)
b = np.array([10, 20])         # (2,) → 补1为(1,2)
# a广播为(3,2),b广播为(3,2),再运算
print(a + b)  # [[11 21],[12 22],[13 23]]

# 示例4:不满足广播规则(报错)
c = np.array([[1, 2], [3, 4]])  # (2,2)
d = np.array([1, 2, 3])         # (3,) → 补1为(1,3),2≠3,报错
# print(c + d)  # ValueError: operands could not be broadcast together with shapes (2,2) (1,3)

五、NumPy常用函数(分模块,实战全覆盖)

NumPy提供了上千个内置函数 ,覆盖数值计算、线性代数、统计分析、随机数、逻辑判断等所有场景,无需手动实现。以下按实战使用频率分类讲解核心函数,均为必记内容。

1. 基础数学函数(np.xxx

覆盖所有常用数学运算,均支持向量化操作,直接作用于整个数组。

python 复制代码
import numpy as np

arr = np.array([1, -2, 3, -4, 5])
# 绝对值、平方、开方
print("绝对值:", np.abs(arr))        # [1 2 3 4 5]
print("平方:", np.square(arr))      # [ 1  4  9 16 25]
print("开方:", np.sqrt(np.abs(arr))) # [1.         1.41421356 1.73205081 2.         2.23606798]

# 指数、对数(np.exp: e^x;np.log: 自然对数;np.log10: 以10为底)
print("指数:", np.exp([1, 2, 3]))    # [ 2.71828183  7.3890561  20.78460969]
print("自然对数:", np.log([1, e, e**2]))  # [0. 1. 2.]

# 三角函数、反三角函数
print("正弦:", np.sin(np.pi/2))      # 1.0
print("反正切:", np.arctan(1))       # 0.7853981633974483(π/4)

# 取整函数(np.round: 四舍五入;np.ceil: 向上取整;np.floor: 向下取整;np.trunc: 截断小数)
arr_float = np.array([1.2, 1.9, -2.3, -2.8])
print("四舍五入:", np.round(arr_float))  # [ 1.  2. -2. -3.]
print("向上取整:", np.ceil(arr_float))   # [ 2.  2. -2. -2.]
print("向下取整:", np.floor(arr_float))  # [ 1.  1. -3. -3.]

2. 统计函数(np.xxx/arr.xxx,两种调用方式)

用于数组的统计分析,核心支持按指定维度计算axis参数),是数据分析的基础,两种调用方式完全等价(np.sum(arr) = arr.sum())。

核心统计函数+axis参数使用(重点)
python 复制代码
import numpy as np

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 全局统计(无axis)
print("全局求和:", arr2d.sum())    # 45
print("全局均值:", arr2d.mean())  # 5.0
print("全局最大值:", arr2d.max())  # 9
print("全局最小值:", arr2d.min())  # 1
print("方差:", arr2d.var())        # 6.666666666666667
print("标准差:", arr2d.std())      # 2.581988897471611
print("中位数:", np.median(arr2d)) # 5.0(注意:中位数只有np.xxx方式)
print("求和积:", arr2d.prod())    # 362880(1×2×3×...×9)

# 按维度统计(axis=0:按行,列维度聚合;axis=1:按列,行维度聚合)
print("按行求和(每列的和):", arr2d.sum(axis=0))  # [12 15 18]
print("按列求均值(每行的均值):", arr2d.mean(axis=1))  # [2. 5. 8.]
print("按行求最大值(每列的最大值):", arr2d.max(axis=0))  # [7 8 9]

# 拓展:找最大/最小值的索引(argmax/argmin)
print("全局最大值索引:", arr2d.argmax())  # 8(一维索引)
print("按列求最小值索引(每行的最小值索引):", arr2d.argmin(axis=1))  # [0 0 0]

3. 线性代数函数(np.linalg.xxx

NumPy的np.linalg模块是线性代数计算的核心,提供了矩阵乘法、逆矩阵、行列式、特征值等所有线性代数常用操作,适用于矩阵计算、机器学习模型求解等场景。

注意 :NumPy中数组的*是元素级乘法矩阵乘法需用np.dot()@(Python3.5+,推荐)

python 复制代码
import numpy as np
from numpy import linalg as la  # 别名,简化调用

# 矩阵定义(二维数组)
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
v = np.array([1, 2])

# 1. 矩阵乘法:np.dot(A,B) / A @ B
print("矩阵乘法:\n", A @ B)  # [[19 22],[43 50]]
# 矩阵与向量乘法
print("矩阵与向量乘法:", A @ v)  # [5 11]

# 2. 逆矩阵:la.inv(A)(仅方阵可求逆,且行列式≠0)
A_inv = la.inv(A)
print("A的逆矩阵:\n", A_inv)
print("A × A逆 = 单位矩阵:\n", np.round(A @ A_inv))  # [[1. 0.],[0. 1.]]

# 3. 行列式:la.det(A)
print("A的行列式:", la.det(A))  # -2.0000000000000004

# 4. 特征值与特征向量:la.eig(A)
eigenvalues, eigenvectors = la.eig(A)
print("特征值:", eigenvalues)    # [-0.37228132  5.37228132]
print("特征向量:\n", eigenvectors)

# 5. 转置(简单操作,用A.T即可)
print("A的转置:\n", A.T)  # [[1 3],[2 4]]

4. 逻辑与条件函数(实战高频)

用于数组的条件判断、值替换,替代繁琐的循环条件,核心是np.where()(三目运算符向量化)。

python 复制代码
import numpy as np

arr = np.array([1, -2, 3, -4, 5, -6])
# 1. np.where(条件, 满足条件的值, 不满足条件的值) → 三目运算符向量化(实战最常用)
# 示例:将负数替换为0,正数保持不变
new_arr = np.where(arr > 0, arr, 0)
print("负数替换为0:", new_arr)  # [1 0 3 0 5 0]

# 示例:将大于3的数设为10,小于-2的设为-10,其余保持不变
new_arr2 = np.where(arr > 3, 10, np.where(arr < -2, -10, arr))
print("多条件替换:", new_arr2)  # [  1  -2   3 -10  10 -10]

# 2. np.any():任意元素满足条件返回True;np.all():所有元素满足条件返回True
print("是否有正数:", np.any(arr > 0))  # True
print("是否所有元素都大于0:", np.all(arr > 0))  # False

# 3. np.unique():去重并排序(返回去重后的数组+索引+计数,实战常用)
arr_dup = np.array([3, 1, 2, 3, 1, 2, 4])
unique_arr, counts = np.unique(arr_dup, return_counts=True)
print("去重数组:", unique_arr)  # [1 2 3 4]
print("元素计数:", counts)      # [2 2 2 1]

# 4. np.clip():限制数组元素的范围(超出范围则截断)
arr_clip = np.array([1, -2, 3, 8, 5])
clipped_arr = np.clip(arr_clip, 0, 5)  # 最小值0,最大值5
print("范围限制后:", clipped_arr)  # [1 0 3 5 5]

5. 随机数函数(np.random.xxx,补充)

除了基础的随机数生成,np.random还有两个实战高频函数:打乱数组随机选择

python 复制代码
import numpy as np

np.random.seed(42)  # 固定种子,可复现
arr = np.arange(10)

# 1. np.random.shuffle():原地打乱数组(一维/二维)
np.random.shuffle(arr)
print("打乱后数组:", arr)  # [6 3 7 4 5 0 1 2 9 8]

# 2. np.random.choice():从数组中随机选择元素
# choice(数组, 选择个数, replace=True/False(是否可重复), p=概率分布)
sample1 = np.random.choice(arr, 3)  # 随机选3个,可重复
sample2 = np.random.choice(arr, 3, replace=False)  # 随机选3个,不重复
sample3 = np.random.choice([0,1], 5, p=[0.2, 0.8])  # 按概率选(0占20%,1占80%)

print("随机选择3个(可重复):", sample1)
print("随机选择3个(不重复):", sample2)
print("按概率选择:", sample3)

六、NumPy数组的输入与输出(IO操作)

实战中常需将NumPy数组保存到文件从文件加载数组 ,NumPy提供了专门的IO函数,支持专用格式(npy/npz)文本格式(csv/txt),兼顾效率和可读性。

1. 保存/加载NumPy专用格式(npy/npz)------推荐

  • npy :保存单个 ndarray数组,二进制格式,保存/加载速度最快,不丢失数组属性(shape、dtype等);
  • npz :保存多个ndarray数组,压缩二进制格式,自动将数组封装为字典。
python 复制代码
import numpy as np

# 准备数组
arr1 = np.array([1, 2, 3])
arr2 = np.array([[4, 5], [6, 7]])

# 1. 保存单个数组:np.save(文件名, 数组) → 自动加.npy后缀
np.save("single_arr.npy", arr1)

# 2. 保存多个数组:np.savez(文件名, 数组1名=数组1, 数组2名=数组2) → 自动加.npz后缀
np.savez("multi_arr.npz", arr1=arr1, arr2=arr2)

# 3. 加载单个数组:np.load(文件名)
loaded_arr1 = np.load("single_arr.npy")
print("加载的单个数组:", loaded_arr1)

# 4. 加载多个数组:np.load(文件名) → 返回字典,通过键获取数组
loaded_multi = np.load("multi_arr.npz")
print("加载的多个数组-arr1:", loaded_multi["arr1"])
print("加载的多个数组-arr2:", loaded_multi["arr2"])

2. 保存/加载文本格式(csv/txt)------易读性强

适用于需要人工查看与其他语言/工具交互 的场景,核心函数np.savetxt()(保存)、np.loadtxt()(加载),支持指定分隔符、数据类型、跳过行等。

python 复制代码
import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 1. 保存为文本文件:np.savetxt(文件名, 数组, delimiter=分隔符, fmt=格式)
np.savetxt("arr.csv", arr, delimiter=",", fmt="%d")  # 逗号分隔,整数格式
np.savetxt("arr.txt", arr, delimiter="\t", fmt="%.2f")  # 制表符分隔,保留2位小数

# 2. 从文本文件加载:np.loadtxt(文件名, delimiter=分隔符, dtype=数据类型)
loaded_csv = np.loadtxt("arr.csv", delimiter=",", dtype=np.int32)
loaded_txt = np.loadtxt("arr.txt", delimiter="\t", dtype=np.float32)

print("从csv加载:\n", loaded_csv)
print("从txt加载:\n", loaded_txt)

# 拓展:加载带表头的csv → skiprows=1(跳过第一行)
# np.loadtxt("with_header.csv", delimiter=",", skiprows=1)

七、NumPy实战最佳实践(避坑+效率提升)

结合实战经验,总结10条NumPy核心最佳实践,帮助你写出高效、健壮、易维护的代码,规避常见坑点。

1. 始终使用import numpy as np

这是Python数据分析领域的行业通用约定 ,所有第三方库(Pandas、Scikit-learn)均遵循,使用别名np可大幅简化代码,提升可读性。

2. 优先使用向量化操作,彻底抛弃Python原生循环

这是NumPy效率的核心,任何需要循环遍历数组的场景,都有对应的向量化解决方案 (如条件判断用np.where(),统计用arr.sum()),数据量越大,向量化优势越明显。

3. 合理选择数据类型(dtype),节省内存

  • 常规整数计算用np.int32,大数值用np.int64,避免默认的int64浪费内存;
  • 常规浮点计算用np.float32(如机器学习模型训练),高精度计算用np.float64(NumPy默认,推荐);
  • 避免用NumPy存储字符串,字符串处理优先使用Pandas的str方法。

4. 明确区分视图(view)和拷贝(copy),显式拷贝用arr.copy()

  • 基础切片返回视图,若需独立使用子集,务必显式调用arr.copy() 创建拷贝,避免修改视图导致原数组数据混乱;
  • 花式索引、布尔索引返回拷贝,可直接修改,无需额外拷贝。

5. 利用reshape(-1)快速展平数组,替代flatten()/ravel()

reshape(-1)通用的展平方法,支持任意维度数组展平为一维,且返回视图(高效),是实战中展平数组的首选:

python 复制代码
arr = np.array([[1,2],[3,4],[5,6]])
flat_arr = arr.reshape(-1)  # [1 2 3 4 5 6](推荐)

6. 矩阵乘法用@np.dot(),拒绝使用*

NumPy中*元素级乘法 ,并非矩阵乘法,矩阵乘法必须用@(Python3.5+,简洁推荐)或np.dot(),避免因乘法符号错误导致计算结果错误。

7. 固定随机种子,保证实验可复现

使用np.random.seed(n)(n为任意整数)固定随机数种子,确保每次运行代码生成的随机数完全相同,这是机器学习、模拟实验中保证结果可复现的关键。

8. 优先使用np.vstack()/np.hstack(),替代np.concatenate()

np.vstack()(垂直拼接)、np.hstack()(水平拼接)无需指定axis参数,更符合人类直觉,代码更简洁,且完全等价于np.concatenate(),是实战中数组拼接的首选。

9. 处理缺失值用np.isnan()/np.isfinite(),避免直接比较

NumPy中缺失值用np.nan表示,np.nan == np.nan返回False,无法通过直接比较判断缺失值,必须用专用函数:

python 复制代码
arr = np.array([1, np.nan, 3, np.inf, 5])
print("缺失值位置:", np.isnan(arr))  # [False  True False False False]
print("有限值位置:", np.isfinite(arr))  # [ True False  True False  True]

10. 大数组运算避免频繁创建中间数组

NumPy的数组运算会创建中间数组(如a + b * c会先创建b*c的中间数组),大数组运算时可通过原地操作arr += 1)或指定out参数减少中间数组创建,提升效率:

python 复制代码
a = np.ones(10**6)
b = np.ones(10**6)
c = np.empty(10**6)
np.add(a, b, out=c)  # 将a+b的结果直接存入c,不创建中间数组(推荐)

11. 与Python原生列表转换用tolist(),而非list()

将ndarray转为Python原生列表时,arr.tolist()list(arr)更高效 ,且支持多维数组转换为嵌套列表,list(arr)仅能将多维数组转为一维列表的嵌套:

python 复制代码
arr2d = np.array([[1,2],[3,4]])
print(arr2d.tolist())  # [[1,2],[3,4]](推荐,嵌套列表)
print(list(arr2d))     # [array([1,2]), array([3,4])](不推荐)

八、NumPy核心知识点总结

  1. NumPy是Python科学计算的核心基础库,是Pandas、Matplotlib、机器学习库的底层依赖,核心优势是高性能、向量化、多维支持
  2. 核心对象是ndarray多维数组,同构存储 是其高效的关键,与Python原生列表的核心区别是元素类型统一、内存连续
  3. ndarray的创建方式包括:np.array()(列表转换)、np.zeros()/np.ones()(固定值)、np.arange()/np.linspace()(有序值)、np.random(随机数);
  4. 核心属性:ndim(维度)、shape(形状)、size(元素数)、dtype(数据类型),是操作数组的基础;
  5. 索引与切片支持基础切片、花式索引、布尔索引,布尔索引是实战中条件筛选的首选;
  6. 向量化操作广播机制是NumPy高效的核心,无需循环,直接对整个数组运算,广播需遵守"从后比,相等或为1"的规则;
  7. 常用函数覆盖数学计算、统计分析、线性代数、随机数、条件判断 ,均支持向量化,np.where()是实战高频的条件函数;
  8. 数组IO支持npy/npz(高效)csv/txt(易读),npy/npz是NumPy专用格式,推荐实战使用;
  9. 实战最佳实践:优先向量化、合理选择dtype、明确视图/拷贝、矩阵乘法用@、固定随机种子、高效转换列表。
相关推荐
啊阿狸不会拉杆2 小时前
《机器学习导论》第 1 章 - 引言
人工智能·python·算法·机器学习·ai·numpy·matplotlib
Dfreedom.3 小时前
详解四大格式(PIL/OpenCV/NumPy/PyTorch)的转换原理与场景选择
图像处理·人工智能·pytorch·opencv·numpy·pillow
不懒不懒3 小时前
【机器学习:下采样 VS 过采样——逻辑回归在信用卡欺诈检测中的实践】
python·numpy·scikit-learn·matplotlib·pip·futurewarning
小白开始进步20 小时前
JAKA Zu12 机械臂运动学算法深度解析(含可视化方案)
python·算法·numpy
肾透侧视攻城狮2 天前
《解锁 PyTorch 张量:多维数据操作与 GPU 性能优化全解析》
人工智能·numpy·张量的索引和切片·张量形状变换·张量数学运算操作·张量的gpu加速·张量与 numpy 的互操作
七夜zippoe4 天前
NumPy高级:结构化数组与内存布局优化实战指南
python·架构·numpy·内存·视图
waves浪游6 天前
Ext系列文件系统
linux·服务器·开发语言·c++·numpy
强化试剂瓶7 天前
Silane-PEG8-DBCO,硅烷-聚乙二醇8-二苯并环辛炔技术应用全解析
python·flask·numpy·pyqt·fastapi
Python-AI Xenon8 天前
RHEL / CentOs 7.9 离线升级OpenSSH完整指南
linux·centos·numpy