一、为什么学到数据分析,几乎绕不开 NumPy
如果你前面一直用 Python 列表做数据处理,一开始其实感觉还不错。
存一组数字可以用列表。 循环计算也能做。 求和、筛选、排序,看起来都能完成。
但只要数据量一大,或者开始做成批计算,你很快就会发现两个问题。
第一个问题是慢。 第二个问题是写起来啰嗦。
比如你有一组数据,想让每个数都乘以 2。 用列表你通常会这样写:
nums = [1, 2, 3, 4, 5]result = []for n in nums: result.append(n * 2)print(result)
这当然没错,但当数据变成几十万、几百万个时,纯 Python 循环就会越来越吃力。
再比如你有一个二维表格数据,想对整列求平均值、对整块数据做加减乘除、做筛选、做切片、做矩阵计算。 这时候你会发现,列表虽然能装数据,但它并不是为高效数值计算而生的。
NumPy 出现,就是为了解决这个问题。
它不是“换一种列表写法”这么简单。 它是 Python 里做科学计算、数值计算、数据分析的基础工具之一。
很多后面的库,比如 Pandas、SciPy、scikit-learn、很多机器学习和数据分析工具,底层都和 NumPy 有很深的关系。
所以学 NumPy,不只是学一个库,更是在学 Python 数据计算的地基。
二、NumPy 到底是什么
NumPy 的名字来自 Numerical Python,也就是数值计算版 Python。
你可以把它理解成:
专门为高效处理大量数字数据而设计的工具库。
它最核心的能力主要有两类。
第一类,提供一种更适合数值运算的数据结构。 这个数据结构叫 ndarray,也就是多维数组。
第二类,提供大量高效、现成的数学计算能力。 包括加减乘除、统计、线性代数、随机数、数组变形、切片筛选等。
所以 NumPy 不是为了替代 Python 本身,而是为了补上 Python 在大规模数值计算上的短板。
简单说:
普通 Python 列表,适合一般数据存放。 NumPy 数组,适合大量数字运算。
三、为什么大家做数据计算都爱用它
原因其实非常现实,不神秘。
1. 计算快
NumPy 的很多底层实现不是纯 Python 循环,而是更接近底层的高效实现。 所以同样是大批量数字运算,NumPy 通常会比 Python 原生列表快很多。
2. 写法简洁
很多原本要写循环的计算,在 NumPy 里直接一行就能完成。 这不只是省代码,更重要的是逻辑更清楚。
3. 天然适合矩阵和表格数据
一维数组、二维数组、多维数组,这些都很适合表示真实世界里的数值数据。 比如成绩表、销售表、图像像素、传感器数据、坐标数据。
4. 它是很多数据分析库的基础
后面你学 Pandas,会发现很多底层数据能力和 NumPy 脱不开关系。 所以 NumPy 早学一点,后面会更顺。
四、先安装 NumPy
如果你的环境里还没有装,可以先安装:
python -m pip install numpy
安装完以后,最常见的导入方式是:
import numpy as np
为什么大家都写成 np。 因为 numpy 这个名字有点长,而 np 已经成了几乎默认的约定俗成写法。
所以你以后看到:
import numpy as np
不要觉得陌生,这就是最常见、最标准的写法之一。
五、NumPy 最核心的对象:ndarray
学 NumPy,第一步必须把 ndarray 理解清楚。
它全名叫 n-dimensional array,也就是 n 维数组。 你可以把它理解成:
比列表更适合做数字计算的一种数组对象。
先看最简单的创建方式:
import numpy as nparr = np.array([1, 2, 3, 4, 5])print(arr)print(type(arr))
输出大致会像这样:
[12345]<class 'numpy.ndarray'>
这里你要注意两个点。
第一,它看起来有点像列表,但它不是列表。 第二,它是 NumPy 最基础的操作对象,后面绝大多数计算都会围绕它展开。
六、列表和 NumPy 数组,看起来像,行为却不完全一样
先看 Python 列表:
a = [1, 2, 3]b = [4, 5, 6]print(a + b)
结果是:
[1, 2, 3, 4, 5, 6]
也就是说,列表的 + 是拼接,不是逐元素相加。
再看 NumPy 数组:
import numpy as npa = np.array([1, 2, 3])b = np.array([4, 5, 6])print(a + b)
结果是:
[579]
这就非常关键了。
NumPy 数组的很多运算,是按元素来的。 这意味着你不需要自己写循环,它就能帮你把数组中每个位置对应起来做计算。
这正是它适合数值计算的核心原因之一。
七、创建数组的几种常见方式
最常用的是 np.array():
import numpy as nparr1 = np.array([1, 2, 3])arr2 = np.array([[1, 2, 3], [4, 5, 6]])print(arr1)print(arr2)
第一个是一维数组。 第二个是二维数组。
除了直接从列表创建,NumPy 还提供很多快速生成数组的方法。
生成全 0 数组:
import numpy as nparr = np.zeros(5)print(arr)
生成全 1 数组:
arr = np.ones(5)print(arr)
生成指定形状的二维全 0 数组:
arr = np.zeros((2, 3))print(arr)
生成连续整数:
arr = np.arange(0, 10)print(arr)
它会得到 0 到 9。
按固定间隔生成:
arr = np.arange(0, 10, 2)print(arr)
输出:
[02468]
生成等间距数字:
arr = np.linspace(0, 1, 5)print(arr)
它表示从 0 到 1 之间,平均分成 5 个点。 这在画图、数值分析里很常用。
所以你要慢慢习惯,NumPy 不只是“接收现有列表”,它本身就能很方便地制造测试数据和计算数据。
八、一维、二维、多维,到底怎么理解
这部分一定要建立直觉。
一维数组:
np.array([1, 2, 3, 4])
可以理解成一排数字。
二维数组:
np.array([[1, 2, 3], [4, 5, 6]])
可以理解成一个表格,两行三列。
三维及以上,刚入门时不用想得太复杂。 你可以把它理解成“多层表格堆叠起来”。
很多初学者一看到“多维数组”就紧张。 其实前期你最常打交道的,主要是一维和二维。
一维,像一列成绩。 二维,像一张成绩表。 这就够你先把多数基础操作学明白了。
九、数组的形状 shape,非常重要
NumPy 里有一个特别高频的属性:shape
它表示数组的形状,也就是每个维度有多大。
比如:
import numpy as nparr = np.array([1, 2, 3, 4])print(arr.shape)
输出通常是:
(4,)
表示它是一维数组,长度为 4。
再看二维数组:
arr = np.array([[1, 2, 3], [4, 5, 6]])print(arr.shape)
输出通常是:
(2, 3)
表示它有 2 行 3 列。
你后面做切片、变形、矩阵运算时,shape 会非常常用。 因为很多操作能不能做,首先取决于形状对不对。
十、数组有几维,看 ndim
如果你想知道一个数组到底是几维,可以看 ndim。
import numpy as nparr1 = np.array([1, 2, 3])arr2 = np.array([[1, 2, 3], [4, 5, 6]])print(arr1.ndim)print(arr2.ndim)
输出通常是:
12
这很直观。 一个是一维,一个是二维。
同时你也可以看总元素个数:
print(arr2.size)
以及数据类型:
print(arr2.dtype)
这些属性以后你会经常碰到。
十一、dtype:数组里的元素类型为什么值得单独讲
普通列表里,可以什么类型混着放:
data = [1, "hello", True]
但 NumPy 更强调数值计算,所以它通常希望数组里的数据类型尽可能统一。 这样底层计算效率更高。
看例子:
import numpy as nparr = np.array([1, 2, 3, 4])print(arr.dtype)
可能输出:
int64
如果你写:
arr = np.array([1.1, 2.2, 3.3])print(arr.dtype)
则可能是:
float64
你也可以手动指定类型:
arr = np.array([1, 2, 3], dtype=float)print(arr)print(arr.dtype)
输出大致是:
[1.2.3.]float64
为什么这很重要。
因为真实计算里,整数和浮点数的行为不一样。 内存占用、精度、除法结果、后续模型计算,都可能受 dtype 影响。
入门阶段你不用死记各种类型名,但至少要知道:
NumPy 数组会关心数据类型,而且这件事会影响计算结果和性能。
十二、NumPy 最爽的地方:向量化运算
这是 NumPy 的灵魂之一。
所谓向量化运算,你可以先把它理解成:
直接对整组数据做计算,而不是自己一项一项写循环。
比如数组每个元素都加 10:
import numpy as nparr = np.array([1, 2, 3, 4, 5])print(arr + 10)
输出:
[1112131415]
每个元素都乘 2:
print(arr * 2)
输出:
[ 246810]
每个元素都平方:
print(arr ** 2)
输出:
[ 1491625]
这就是为什么很多数据计算都爱用 NumPy。 因为很多本来要写循环的事,它天然就支持整组处理。
这不仅更简洁,通常也更高效。
十三、数组之间的运算
数组和数组之间,也常常是按元素对应计算。
import numpy as npa = np.array([1, 2, 3])b = np.array([4, 5, 6])print(a + b)print(a - b)print(a * b)print(a / b)
结果大致是:
[579][-3-3-3][ 41018][0.250.40.5 ]
这里你一定要注意,不是拼接,不是套娃,而是逐元素运算。
当然,这种运算一般要求形状能对应得上。 如果形状不匹配,后面你会学到广播机制,有些情况也能算,有些情况会报错。
入门阶段先记住最基本的情况:
形状相同的数组,通常能按元素对应运算。
十四、索引和切片,和列表很像,但又更强
NumPy 数组的基础索引和切片,和列表有相似之处。
比如一维数组:
import numpy as nparr = np.array([10, 20, 30, 40, 50])print(arr[0])print(arr[2])print(arr[1:4])
输出大致是:
1030[203040]
二维数组就更有意思了:
arr = np.array([[1, 2, 3], [4, 5, 6]])print(arr[0])print(arr[1])print(arr[0, 1])print(arr[1, 2])
输出大致是:
[123][456]26
这里的 arr[0, 1] 表示第 0 行第 1 列。 这种写法比列表嵌套索引更直接,也更清晰。
再看二维切片:
arr = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9]])print(arr[:2, :2])
输出大致是:
[[12] [45]]
意思是取前两行、前两列。
NumPy 的切片能力非常强,后面做数据分析、图像处理、矩阵操作时会频繁用到。
十五、reshape:改变数组形状
这个方法特别常用。
你可能有一维数据,但想把它变成二维表格; 或者你有二维数据,想重新整理成别的结构。 这时候就要用 reshape()。
import numpy as nparr = np.arange(1, 13)print(arr)
输出:
[ 123456789101112]
把它改成 3 行 4 列:
new_arr = arr.reshape(3, 4)print(new_arr)
输出大致是:
[[ 1234] [ 5678] [ 9101112]]
这时你要有个常识:
改形状时,总元素个数必须对得上。 原来是 12 个数,变形后也必须还是 12 个位置。
你也可以用 -1 让 NumPy 自动推算:
new_arr = arr.reshape(3, -1)print(new_arr)
意思是行数固定为 3,列数你自己算。
这在实际开发里很好用。
十六、常见统计函数:求和、平均值、最大值、最小值
NumPy 作为数值计算库,这类操作当然非常常见。
import numpy as nparr = np.array([1, 2, 3, 4, 5])print(arr.sum())print(arr.mean())print(arr.max())print(arr.min())
输出大致是:
153.051
如果是二维数组,还可以按行或按列统计。
arr = np.array([ [1, 2, 3], [4, 5, 6]])print(arr.sum())print(arr.sum(axis=0))print(arr.sum(axis=1))
整体求和是所有元素加起来。axis=0 表示按列处理。axis=1 表示按行处理。
输出大致会是:
21[579][ 615]
这一部分你刚接触时容易被 axis 绕晕。 先记一个最实用的直觉:
二维数组里axis=0 常常和“列”有关axis=1 常常和“行”有关
后面你会越用越顺。
十七、布尔筛选,是 NumPy 另一个非常强的点
假设你有一组成绩,只想找出大于 60 的值。
import numpy as npscores = np.array([55, 68, 72, 49, 90, 61])print(scores > 60)
输出:
[FalseTrueTrueFalseTrueTrue]
这表示每个位置是否满足条件。
更重要的是,你可以直接拿它筛选:
print(scores[scores > 60])
输出:
[68729061]
这就很强了。
不用自己写循环,不用 append,不用 if 判断一项项塞。 你直接写条件,NumPy 就能帮你筛出结果。
你还可以组合条件,比如:
print(scores[(scores > 60) & (scores < 80)])
输出:
[687261]
注意这里用的是 &,不是 and。 这是 NumPy 布尔条件里一个很常见的细节。
十八、NumPy 数组和列表的一个重要区别:切片可能共享数据
这个点初学者很容易忽略。
看例子:
import numpy as nparr = np.array([1, 2, 3, 4, 5])sub = arr[1:4]sub[0] = 200print(arr)print(sub)
很多人会以为只改了 sub,原数组不会变。 但在 NumPy 里,某些切片操作得到的不是完全独立的新数组,而是原数据的一个视图。
所以输出大致可能是:
[ 1200345][20034]
这和很多人对列表切片的直觉不太一样。
如果你明确要复制一份独立数据,可以用:
sub = arr[1:4].copy()
这在后面处理数据时非常重要。 不然你以为是在改副本,结果把原数据也一起改了。
十九、NumPy 为什么快,先理解个大概就够了
入门阶段不需要你追底层源码,但最好知道个方向。
NumPy 快,主要不是因为它“语法神奇”,而是因为:
它的数据结构更紧凑 数据类型更统一 很多运算底层实现更高效 避免了大量 Python 层面的显式循环
也就是说,NumPy 快,不是快在你少打字。 而是快在底层执行方式就不是普通列表那套逻辑。
所以以后你看到“向量化运算更快”,要理解成:
不是一行代码有魔法,而是它把循环和运算交给了更高效的底层实现。
二十、一个直观对比:为什么不用列表硬算
先看列表写法:
nums = [1, 2, 3, 4, 5]result = []for n in nums: result.append(n * 10 + 1)print(result)
再看 NumPy:
import numpy as npnums = np.array([1, 2, 3, 4, 5])result = nums * 10 + 1print(result)
逻辑一眼就清楚很多。
当运算越来越复杂时,这种差距会更明显。 比如批量标准化、归一化、矩阵运算、整列处理、条件筛选。 如果都手写循环,代码会越来越臃肿。 NumPy 则更接近“直接表达你想做的数学操作”。
二十一、一个小案例:学生成绩处理
假设有 5 个学生的三门成绩:
import numpy as npscores = np.array([ [85, 90, 78], [92, 88, 95], [76, 81, 79], [60, 65, 70], [99, 97, 98]])
看一下形状:
print(scores.shape)
结果大致是:
(5, 3)
表示 5 行 3 列,也就是 5 个学生、3 门课。
每个学生的总分:
print(scores.sum(axis=1))
每门课的平均分:
print(scores.mean(axis=0))
找出总分超过 270 的学生:
total_scores = scores.sum(axis=1)print(total_scores[total_scores > 270])
如果想给所有成绩统一加 5 分:
new_scores = scores + 5print(new_scores)
你会发现,这类表格数值处理,NumPy 非常顺手。 而这还只是最基础的一层。
二十二、学习 NumPy 时,最容易踩的几个坑
1. 还拿列表思维硬套数组
比如以为 + 还是拼接。 结果发现算出来完全不是自己想的那样。
2. 忽略 shape
很多报错本质上不是运算本身错,而是数组形状对不上。
3. 忽略 dtype
特别是整数和浮点数混用、精度问题、除法结果时,很容易出意外。
4. 切片后直接改值,却不知道改到了原数组
这就是前面提到的视图问题。
5. 把 NumPy 当成“只是更快的列表”
这样理解太浅了。 它本质上是围绕多维数组和数值计算构建的一整套思路。
二十三、这一章学到什么程度算及格
你现在不用追求一下子学完 NumPy 全部内容。 入门阶段,能掌握这些就已经很不错:
知道什么是 ndarray会创建一维和二维数组 会看 shape、ndim、dtype会做基础加减乘除 会做索引和切片 会用 sum()、mean() 这些基础统计 会做简单布尔筛选 知道 NumPy 为什么适合数值计算
只要这几步站稳了,后面再学 Pandas、矩阵处理、绘图、数据分析时,你会明显轻松很多。
二十四、本章要点整理
NumPy 是 Python 里最核心的数值计算库之一。 它最重要的对象是 ndarray,也就是多维数组。 NumPy 数组比普通列表更适合做大量数字计算。 它支持高效的向量化运算,可以直接对整组数据做加减乘除。 常见创建方式有 array()、zeros()、ones()、arange()、linspace()。 数组的重要属性包括 shape、ndim、size、dtype。 NumPy 支持灵活的索引、切片、变形和布尔筛选。 常见统计操作有 sum()、mean()、max()、min()。 NumPy 快,不只是因为写法简洁,更因为它底层实现更适合数值计算。 后面的 Pandas、数据分析、机器学习,很多基础都离不开 NumPy。