1. 认识 NumPy #
- 本章介绍
NumPy 的定位、优势,并带你跑通第一个示例。
- 读完后你会知道为什么要学 NumPy,以及如何验证环境可用。
1.1 NumPy 是什么? #
- NumPy(Numerical Python)是 Python 的数值计算基础库,核心是高性能多维数组
ndarray。
- Python 原生列表做大量数学运算很慢,NumPy 用 C 实现底层,速度可快几十到上百倍。
Pandas、Scikit-learn、Matplotlib 等数据科学库都建立在 NumPy 之上。
- 学习 NumPy 是进入数据分析、机器学习的第一步。
1.2 为什么需要 NumPy? #
- 原生列表逐个循环计算,代码长、速度慢,不适合处理成千上万条数据。
- NumPy 支持向量化:对整个数组一次性做加减乘除,无需手写 for 循环。
- 同类型数据连续存储,内存更省,矩阵运算、统计聚合都有现成函数。
- 项目中读取 CSV、训练模型、处理图像数值,几乎都会用到 NumPy。
1.3 第一个 NumPy 示例 #
- 习惯写法是
import numpy as np,后续用 np.xxx 调用函数。
np.array() 把 Python 列表转成 NumPy 数组。
np.mean() 求平均值,一行代码替代手写循环。
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
average = np.mean(arr)
print(f"数组: {arr}")
print(f"平均值: {average}")
2. 前置知识 #
- 本章补充 ndarray 学习前必须理解的概念。
- 尤其是 axis(轴),后面统计、拼接都会反复用到。
2.1 数组、向量与矩阵 #
- 数组:多个同类型元素组成的数据结构,一维像一行数字,二维像表格。
- 向量:一维数组,如
[1, 2, 3],表示一组数值。
- 矩阵:二维数组,如
[[1, 2], [3, 4]],有行和列。
- 需掌握 Python 基础:列表、
import 导入模块、简单的 for 循环。
2.2 轴(axis)是什么? #
- 二维数组有两个方向:沿行操作或沿列操作,NumPy 用
axis 参数指定方向。
axis=0 表示沿第 0 维(对二维数组来说是按列聚合,得到每列的结果)。
axis=1 表示沿第 1 维(对二维数组来说是按行聚合,得到每行的结果)。
- 记住口诀:「
axis=0 压扁行、axis=1 压扁列」——聚合时消掉的是该轴。
3. 安装与环境 #
- 本章完成 NumPy 的安装与验证。
- 安装成功后即可运行后续所有示例代码。
3.1 安装 NumPy #
- NumPy 不是 Python 内置库,需用 pip 单独安装。
- 安装后执行验证命令,能打印版本号即表示成功。
- 国内网络慢时可加清华镜像加速。
pip install numpy
python -c "import numpy as np; print(np.__version__)"
4. ndarray 基础 #
- 本章讲解 NumPy 最核心的数据结构
ndarray。
- 包括如何创建数组,以及 ndarray 与 Python 列表的关键区别。
4.1 ndarray 对象 #
ndarray(N-dimensional array)是 NumPy 的核心数据结构,存放同类型、多维度数据。
- 下标从
0 开始,元素在内存中连续存储,访问和切片速度很快。
- 与 Python 列表不同:ndarray 要求元素类型一致,且支持向量化运算。
4.2 创建 ndarray #
- 最常用入口是
np.array(),把列表或嵌套列表转成数组。
dtype 可指定元素类型;ndmin 可强制最小维度。
- 一维数组打印为一行数字,二维数组打印为行列表格。
import numpy as np
a = np.array([1, 2, 3])
print("一维:", a)
b = np.array([[1, 2], [3, 4]])
print("二维:\n", b)
c = np.array([1, 2, 3], dtype=float)
print("浮点数组:", c)
4.3 数组与列表的区别 #
- 列表可混合存放不同类型;ndarray 元素类型必须一致。
- 列表
[1,2,3] * 2 是重复拼接;ndarray [1,2,3] * 2 是每个元素乘 2。
- 做数值计算时优先用 ndarray,列表仅作临时输入。
import numpy as np
py_list = [1, 2, 3]
print("列表 * 2:", py_list * 2)
arr = np.array([1, 2, 3])
print("数组 * 2:", arr * 2)
5. 数据类型与数组属性 #
- 本章介绍
dtype 类型系统,以及 shape、ndim、size 等常用属性。
- 理解这些属性是读懂数组结构、做 reshape 的前提。
5.1 数据类型(dtype) #
dtype 决定每个元素占多少内存、如何解释数值。
- 常用类型:
int32、int64、float32、float64、bool_。
- 用
astype() 转换类型;指定 dtype 创建数组可避免隐式转换。
5.2 常用 dtype 与类型转换 #
- 整数默认多为
int64,浮点默认 float64。
- 大数据量时可用
float32 节省内存。
astype() 返回新数组,不修改原数组。
import numpy as np
arr = np.array([1, 2, 3])
print("dtype:", arr.dtype)
float_arr = arr.astype(float)
print("转浮点:", float_arr, float_arr.dtype)
f = np.array([1, 2, 3], dtype=np.float32)
print("float32:", f.dtype)
5.3 数组属性 #
shape:各维度大小,如 (3, 4) 表示 3 行 4 列。
ndim:维度数量(秩),一维为 1,二维为 2。
size:元素总个数,等于 shape 各维乘积。
dtype:元素数据类型。
5.4 查看与修改 shape #
arr.shape 返回元组,描述数组结构。
arr.reshape(行, 列) 改变形状,元素总数不能变。
reshape 返回新视图或新数组,不改变原数据顺序。
import numpy as np
arr = np.arange(12)
print("原形状:", arr.shape)
mat = arr.reshape(3, 4)
print("reshape 后:\n", mat)
print("新形状:", mat.shape)
print("维度数 ndim:", mat.ndim)
print("元素总数 size:", mat.size)
6. 创建数组的常用方法 #
- 本章汇总项目中高频的数组创建方式。
- 包括固定值填充、数值序列、随机数,以及
array 与 asarray 的差异。
6.1 zeros / ones / eye / full #
np.zeros(shape) 创建全 0 数组,初始化累加器常用。
np.ones(shape) 创建全 1 数组。
np.eye(n) 创建 n 阶单位矩阵(对角线为 1)。
np.full(shape, 值) 用指定值填充数组。
shape 传整数表示一维,传元组 (行, 列) 表示二维。
import numpy as np
zeros = np.zeros((3, 4))
print("zeros:\n", zeros)
ones = np.ones((2, 3), dtype=int)
print("ones:\n", ones)
eye = np.eye(3)
print("eye:\n", eye)
full = np.full((2, 2), 7)
print("full:\n", full)
6.2 arange 与 linspace #
np.arange(start, stop, step) 按步长生成序列,不包含 stop(左闭右开)。
np.linspace(start, stop, num) 生成 num 个等间距数,默认包含 stop。
arange 适合整数序列;linspace 适合画图取采样点。
import numpy as np
seq = np.arange(0, 10, 2)
print("arange:", seq)
points = np.linspace(1, 10, 10)
print("linspace:", points)
x = np.linspace(0, 2 * np.pi, 5)
print("x 轴采样:", x)
6.3 随机数组 #
np.random.rand(行, 列) 生成 [0, 1) 均匀分布随机数。
np.random.randint(低, 高, size) 生成随机整数。
np.random.randn(行, 列) 生成标准正态分布随机数。
- 设置
np.random.seed(42) 可固定随机结果,便于复现。
import numpy as np
np.random.seed(42)
rand = np.random.rand(2, 3)
print("rand:\n", rand)
ints = np.random.randint(1, 100, size=5)
print("randint:", ints)
6.4 array 与 asarray #
np.array() 总是尽量创建新数组(可能复制数据)。
np.asarray() 若输入已是 ndarray,可能直接返回原对象,避免多余复制。
- 修改
asarray 结果可能影响原数组;array 结果独立。
import numpy as np
original = np.array([1, 2, 3, 4, 5])
view_like = np.asarray(original)
copy_arr = np.array(original)
original[0] = 99
print("original:", original)
print("asarray 结果:", view_like)
print("array 结果:", copy_arr)
7. 索引与切片 #
- 本章讲解如何读取、筛选数组中的数据。
- 包括基础切片、布尔索引和整数数组索引,是数据清洗的核心技能。
7.1 索引基础 #
- 索引从 0 开始,
arr[0] 是第一个,arr[-1] 是最后一个。
- 二维数组用
arr[行, 列],arr[1, 2] 是第 2 行第 3 列。
- 方括号
[] 是访问和切片的核心语法。
7.2 一维切片 #
arr[start:stop:step] 左闭右开,不包含 stop。
- 省略
start 从 0 开始,省略 stop 到末尾,省略 step 步长为 1。
arr[::-1] 表示反转整个数组。
- 切片通常返回视图,修改切片可能影响原数组。
import numpy as np
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])
print("arr[3]:", arr[3])
print("arr[-1]:", arr[-1])
print("arr[1:5]:", arr[1:5])
print("arr[::2]:", arr[::2])
print("arr[::-1]:", arr[::-1])
7.3 二维切片 #
arr[行切片, 列切片] 可同时切行和列。
arr[:, 0] 取第 0 列;arr[0, :] 取第 0 行。
: 表示该维度全部。
import numpy as np
arr = np.arange(12).reshape(3, 4)
print("原数组:\n", arr)
print("第 2 行:", arr[1, :])
print("第 3 列:", arr[:, 2])
print("子矩阵:\n", arr[0:2, 1:3])
7.4 布尔索引 #
- 用条件表达式生成 True/False 数组,放在
[] 里筛选元素。
arr[arr > 5] 取出所有大于 5 的元素。
- 多条件用
&(与)、|(或),每个条件必须加括号。
import numpy as np
scores = np.array([85, 92, 78, 96, 88, 75])
high = scores[scores > 90]
print("高分:", high)
mid = scores[(scores >= 70) & (scores <= 90)]
print("中等:", mid)
scores[scores < 80] = 80
print("修正后:", scores)
7.5 整数数组索引 #
- 用整数列表指定下标,一次性取出多个位置的元素。
arr[[0, 2, 4]] 取第 0、2、4 个元素。
- 整数数组索引返回副本,修改结果不影响原数组。
import numpy as np
arr = np.array([10, 20, 30, 40, 50])
picked = arr[[0, 2, 3]]
print("picked:", picked)
mat = np.arange(12).reshape(3, 4)
vals = mat[[0, 2], [1, 3]]
print("指定坐标:", vals)
8. 广播与向量化 #
- 本章讲解不同形状数组如何运算,以及为什么要少用 for 循环。
- 广播和向量化是 NumPy 高性能的核心。
8.1 广播(Broadcasting) #
- 不同形状数组运算时,NumPy 自动「扩展」较小数组使形状兼容。
- 标量与数组运算:标量会应用到每个元素,如
arr + 5。
- 数据归一化
(data - mean) / std 也依赖广播。
8.2 广播规则 #
- 从最右边的维度开始对齐比较。
- 某维度长度相同,或其中一个为 1,则可以广播。
- 否则报错
operands could not be broadcast together。
import numpy as np
a = np.array([[0, 0, 0],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]])
b = np.array([1, 2, 3])
print("广播加法:\n", a + b)
arr = np.array([1, 2, 3])
print("arr * 10:", arr * 10)
8.3 向量化:少用 for 循环 #
- NumPy 的设计哲学是向量化:用数组运算代替逐元素循环。
np.sum(arr) 比 for 累加快得多;arr * 2 比循环乘 2 快得多。
- 只有无法用向量化表达时才考虑循环。
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
doubled = arr * 2
print("向量化 *2:", doubled)
print("sum:", np.sum(arr))
print("mean:", np.mean(arr))
9. 数组操作 #
9.1 变形与转置 #
reshape 改变形状;.T 或 np.transpose() 转置(行变列)。
ravel() 展平为一维(通常返回视图);flatten() 展平为副本。
- 机器学习里特征矩阵转置、批次变形经常用到。
import numpy as np
mat = np.arange(6).reshape(2, 3)
print("原矩阵:\n", mat)
print("转置:\n", mat.T)
print("ravel:", mat.ravel())
9.2 数组拼接 #
np.vstack() 垂直拼接(按行上下叠)。
np.hstack() 水平拼接(按列左右拼)。
np.concatenate((a, b), axis=0) 沿指定轴连接,更通用。
vstack 要求列数相同;hstack 要求行数相同。
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
v = np.vstack((a, b))
print("vstack:\n", v)
h = np.hstack((a, b))
print("hstack:\n", h)
c_axis0 = np.concatenate((a, b), axis=0)
print("concatenate axis=0:\n", c_axis0)
c_axis1 = np.concatenate((a, b), axis=1)
print("concatenate axis=1:\n", c_axis1)
9.3 副本与视图 #
- 视图(view):与原数组共享内存,改视图会影响原数组。
- 副本(copy):独立内存,互不影响。
- 切片、
reshape 通常返回视图;.copy() 显式创建副本。
- 不确定时,对要修改的数组先
.copy() 最稳妥。
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
view = arr[1:4]
view[0] = 99
print("切片改视图后,原数组:", arr)
arr2 = np.array([1, 2, 3, 4, 5])
copied = arr2.copy()
copied[0] = 99
print("副本修改后,原数组:", arr2)
print("副本:", copied)
10. 常用函数 #
- 本章汇总项目中最常用的数学、算术、统计和筛选函数。
- 所有函数均支持向量化,传入 ndarray 即可,无需循环。
10.1 数学函数 #
- NumPy 对数组逐元素执行数学函数,无需循环。
- 常用:
np.sqrt、np.abs、np.round、np.exp、np.log。
import numpy as np
arr = np.array([1, 4, 9, 16], dtype=float)
print("sqrt:", np.sqrt(arr))
print("abs:", np.abs(np.array([-1, -2, 3])))
print("round:", np.round(np.array([1.2, 2.5, 3.8]), 1))
10.2 算术运算 #
- 同形状数组用
+、-、*、/ 逐元素运算。
* 是逐元素乘,不是矩阵乘;矩阵乘法用 @ 或 np.dot。
np.sum(arr, axis=) 可沿指定轴求和。
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
print("a + b:", a + b)
print("a * b:", a * b)
u = np.array([1, 2, 3])
v = np.array([4, 5, 6])
print("点积:", u @ v)
print("点积:", np.dot(u, v))
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print("A @ B:\n", A @ B)
10.3 统计函数 #
np.mean 均值,np.std 标准差。
np.min、np.max 最小最大值,np.median 中位数。
- 配合
axis 可沿行或列统计,是数据分析的基本功。
import numpy as np
scores = np.array([85, 90, 78, 92, 88])
print("mean:", np.mean(scores))
print("std:", np.std(scores))
print("min/max:", np.min(scores), np.max(scores))
data = np.array([[80, 90], [70, 85], [95, 88]])
print("列均值:", np.mean(data, axis=0))
print("行均值:", np.mean(data, axis=1))
10.4 排序与条件筛选 #
np.sort(arr) 返回排序后的新数组。
np.argsort(arr) 返回排序后的索引,找排名常用。
np.where(条件, 满足值, 不满足值) 按条件赋值。
np.clip(arr, min, max) 把值截断到指定范围。
import numpy as np
arr = np.array([30, 10, 50, 20])
print("sort:", np.sort(arr))
print("argsort:", np.argsort(arr))
vals = np.array([-2, 5, -1, 8])
fixed = np.where(vals < 0, 0, vals)
print("where:", fixed)
clipped = np.clip(np.array([0, 50, 120, 30]), 10, 100)
print("clip:", clipped)