简介:numpy是Python科学计算的基石,核心是n维数组对象ndarray。本文用通俗语言讲清numpy的定位与优势、它与Python列表的区别、安装步骤、数组与“轴”的概念、常用创建方式、索引切片、广播机制与向量化运算,并配可运行的代码示例,帮你快速建立数组思维,为数据分析与机器学习打下扎实基础。
numpy是许多开发者从“写脚本”迈向“做数据”的第一站,但初学者常被“多维数组”“广播”“向量化”这些词劝退。其实这些概念并不神秘,下面用通俗的语言和完整的代码示例,把numpy一次讲透。
一言以蔽之:numpy是Python中基于数组对象的科学计算基础库。把它拆开,可以提炼出三个关键词:
Python能成为数据科学领域的主流语言,numpy居功至伟——大量数据分析和机器学习相关的框架,都直接以numpy数组作为最基础的数据交换格式。先把numpy吃透,后续学习任何数据处理、算法建模的内容都会顺畅得多。
Python自带的list灵活有余、效率不足,原因有三:
ndarray的设计正好反其道而行之:
示意对比:
import numpy as npdata = [1, 2, 3, 4, 5]# 纯Python:列表推导式逐元素计算result_list = [x ** 2 for x in data]# numpy:直接对整块数组运算arr = np.array(data)result_arr = arr ** 2# array([ 1, 4, 9, 16, 25])
两段代码都只有一行,但当数据量达到十万、百万级时,数组写法通常能取得数倍乃至数十倍的性能优势(具体取决于任务规模与硬件环境),内存占用也更低。这就是“能用数组就不写循环”的由来。
numpy是一个标准的Python库,用Python官方自带的包管理工具pip即可安装。装好Python后,打开系统的命令行终端,执行:
pip install numpy
验证安装是否成功:
python -c "import numpy; print(numpy.__version__)"
能正常打印版本号即说明环境就绪。两点补充:其一,若下载速度较慢,可以配置镜像源加速;其二,如果使用的是某些科学计算发行版环境,也可以用其自带的包管理工具安装,效果等同。此外,本地机器配置有限时,还可以在百度智能云等云平台开通一台云服务器,用同样的方式搭建Python环境,为后续更大规模的计算留出资源余量。
ndarray是一系列同类数据的集合,可以进行索引、切片和迭代。理解它最关键的概念是轴(axis):
import numpy as nparr3d = np.array([[[ 0, 1, 2], [ 3, 4, 5]],[[ 6, 7, 8], [ 9, 10, 11]]])print(arr3d.shape) # (2, 2, 3):2张"表格",每张2行3列print(arr3d.ndim) # 3:共三个轴
上面这个数组可以理解成:一摞共2张表格,每张表格2行、3列。以此类推,n维数组就是n个轴。实际应用里,一张彩色图片本质上就是一个三维数组(高×宽×3个颜色通道),这个类比能帮你迅速建立直觉。
日常调试时,最常用的三个“体检属性”是:
1. 从Python序列创建
import numpy as np# 一维数组,并显式指定类型为inta = np.array([1, 2, 3], dtype=int)# array([1, 2, 3])# 二维数组:传入嵌套序列即可b = np.array(((1, 2), (3, 4)))'''array([[1, 2],[3, 4]])'''
numpy会自动推断元素类型,但在需要严格控制计算性质时(比如保证整数运算不被转成浮点),显式写明dtype是更稳妥的习惯。
2. 按区间生成
np.arange的用法类似Python内置的range,同样是左闭右开:
np.arange(1, 6)# array([1, 2, 3, 4, 5])np.arange(0, 10, 2) # 起点0、终点10(不含)、步长2# array([0, 2, 4, 6, 8])np.arange(6).reshape(2, 3) # 生成后重塑为2行3列'''array([[0, 1, 2],[3, 4, 5]])'''
3. 按形状批量生成
初始化和占位时的高频工具:
np.zeros((2, 3)) # 全0数组np.ones((2, 3)) # 全1数组np.full((2, 3), 7) # 用指定值填充np.linspace(0, 1, 5) # [0,1]之间等间隔取5个点# array([0. , 0.25, 0.5 , 0.75, 1. ])
4. 创建随机数组
模拟数据、随机初始化都离不开随机数组:
import numpy as np# 2行2列、取值范围[0, 1)的均匀分布随机数组np.random.rand(2, 2)'''array([[0.99449146, 0.92339551],[0.1837405 , 0.41719798]])'''# 3行2列、服从标准正态分布的随机数组np.random.randn(3, 2)'''array([[-1.27481003, -1.5888111 ],[ 0.16985203, -2.91526479],[ 1.75992671, -2.81304831]])'''# 在[0, 10)内随机生成2行3列整数np.random.randint(0, 10, size=(2, 3))# 固定随机种子,保证结果可复现np.random.seed(42)
两个新手常踩的坑,特别提醒:其一,rand/randn的形状以独立参数传入,写作rand(2, 2);而zeros/ones等以元组传入,写作zeros((2, 3)),两种风格不同,极易混淆。其二,写实验代码时先固定随机种子,可以让每次运行结果一致,这是保证实验可复现、方便排查问题的基本做法。
a = np.arange(12).reshape(3, 4)'''array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])'''a[1, 2] # 第2行第3列:6a[0] # 第1行:array([0, 1, 2, 3])a[:, 1] # 所有行的第2列:array([1, 5, 9])a[0:2, 1:3] # 前2行、第2~3列构成的子数组
除位置索引外,还有两种高频用法:
一个必须知道的细节:通过基本切片得到的子数组是原数组的视图而非拷贝,修改子数组会同步影响原数组;如果需要独立副本,请显式调用copy()方法。
按数学惯例,两个矩阵形状相同才能相加。但numpy允许形状不同的数组直接运算,靠的就是广播。规则可概括为三条:
最简单的广播是数组与标量:
a = np.array([1, 2, 3])a * 2 # array([2, 4, 6])a + 10 # array([11, 12, 13])
稍复杂一点的例子:
A = np.ones((3, 1)) # 3行1列B = np.ones((1, 4)) # 1行4列A + B # 结果形状为(3, 4)
对照规则:(3,1)与(1,4)从末尾比较——末位1对4(1可拉伸为4),首位3对1(1可拉伸为3),于是双方都按(3, 4)参与运算。如果某对维度既不相等、也没有1,运算会直接报错,此时应先用reshape等方法把形状对齐。理解广播后你会发现:numpy代码之所以能写得很短,一半功劳在向量化,另一半就在广播。
加减乘除、乘方、开方、比较……numpy的运算符和函数都直接作用于整块数组:
a = np.array([1, 2, 3, 4])a + 1 # array([2, 3, 4, 5])a * a # array([ 1, 4, 9, 16])np.sqrt(a) # array([1. , 1.41421356, 1.73205081, 2. ])
统计函数同样一行搞定,并且可通过axis参数指定沿哪个轴计算:
m = np.arange(12).reshape(3, 4)m.sum() # 全局求和:66m.sum(axis=0) # 沿axis 0压扁 → 每列的和:array([12, 15, 18, 21])m.sum(axis=1) # 沿axis 1压扁 → 每行的和:array([ 6, 22, 40])m.mean() # 均值:5.5m.max(axis=1) # 每行最大值:array([ 3, 7, 11])m.std() # 标准差
记忆技巧:axis等于几,就沿第几个轴把数组“压扁”。按行统计还是按列统计,是日常使用中最容易出错、也最值得练熟的点。
把前面所有知识点串起来,做一个数据预处理中最常见的任务——标准化(把每个特征调整为均值0、标准差1):
import numpy as np# 模拟5个样本、3个特征的数据data = np.random.randn(5, 3)mean = data.mean(axis=0) # 每个特征的均值,形状(3,)std = data.std(axis=0) # 每个特征的标准差,形状(3,)normalized = (data - mean) / std
这段代码有两个值得细品的地方:一是axis=0让统计沿样本方向进行,得到的是“每个特征”的统计量;二是data形状为(5, 3),而mean形状为(3,),两者并不相同却能直接相减——这正是广播在幕后把(3,)按行匹配到了(5, 3)。若用纯Python实现同样的逻辑,需要两层嵌套循环外加小心维护下标;两相对比,就能体会numpy的表达力所在。
最后用几句话收束全文:
numpy是数据分析与机器学习绕不开的地基。把“形状”和“轴”两个概念吃透、再理解广播,你遇到的大部分报错都能自行定位。用好numpy之后,你写出的数值计算代码会更短、更快,也更接近数学表达式本身。