跳转到内容

3.2.2 数组基础

NumPy 数组 Shape 与 Axis 图

  • 掌握多种数组创建方式
  • 理解数组的核心属性(shape、dtype、ndim、size)
  • 了解 NumPy 的数据类型系统
  • 掌握数组的数据类型转换

最基本的方式是用 np.array() 把 Python 列表转成 NumPy 数组:

import numpy as np
# 一维数组
a = np.array([1, 2, 3, 4, 5])
print(a) # [1 2 3 4 5]
print(type(a)) # <class 'numpy.ndarray'>
# 二维数组(矩阵)
b = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(b)
# [[1 2 3]
# [4 5 6]]
# 三维数组
c = np.array([
[[1, 2], [3, 4]],
[[5, 6], [7, 8]]
])
print(c.shape) # (2, 2, 2)

NumPy 提供了大量快速创建数组的函数,不需要你手写每个元素:

import numpy as np
# ========== 全 0 / 全 1 数组 ==========
zeros_1d = np.zeros(5)
print(zeros_1d) # [0. 0. 0. 0. 0.]
zeros_2d = np.zeros((3, 4)) # 3 行 4 列
print(zeros_2d)
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
ones_2d = np.ones((2, 3)) # 2 行 3 列
print(ones_2d)
# [[1. 1. 1.]
# [1. 1. 1.]]
# ========== 填充指定值 ==========
fives = np.full((2, 3), 5) # 全部填充 5
print(fives)
# [[5 5 5]
# [5 5 5]]
# ========== 单位矩阵 ==========
eye = np.eye(3) # 3×3 单位矩阵
print(eye)
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
# arange:类似 Python 的 range,但返回 NumPy 数组
a = np.arange(10) # 0 到 9
print(a) # [0 1 2 3 4 5 6 7 8 9]
b = np.arange(2, 10, 2) # 从 2 开始,到 10(不含),步长 2
print(b) # [2 4 6 8]
c = np.arange(0, 1, 0.2) # 支持小数步长!(range 不支持)
print(c) # [0. 0.2 0.4 0.6 0.8]
# linspace:指定个数,自动计算步长
d = np.linspace(0, 10, 5) # 从 0 到 10(含),均匀取 5 个点
print(d) # [ 0. 2.5 5. 7.5 10. ]
e = np.linspace(0, 1, 11) # 0 到 1 之间取 11 个点
print(e) # [0. 0.1 0.2 ... 0.9 1. ]
# 新 NumPy 代码优先使用 default_rng()
rng = np.random.default_rng(seed=42)
# 0~1 之间的均匀分布随机数
rand = rng.random((3, 4)) # 3×4
print(rand)
# 标准正态分布随机数(均值0,标准差1)
randn = rng.standard_normal((3, 4)) # 3×4
# 指定范围的随机整数
randint = rng.integers(1, 100, size=(3, 4)) # 1~99 之间的 3×4 整数
print(randint)
函数作用示例
np.array()从列表创建np.array([1, 2, 3])
np.zeros()全 0 数组np.zeros((3, 4))
np.ones()全 1 数组np.ones((2, 3))
np.full()填充指定值np.full((2, 3), 7)
np.eye()单位矩阵np.eye(4)
np.arange()等差数列(指定步长)np.arange(0, 10, 2)
np.linspace()等差数列(指定个数)np.linspace(0, 1, 100)
rng.random()均匀随机数 [0, 1)rng.random((3, 4))
rng.standard_normal()标准正态分布rng.standard_normal((3, 4))
rng.integers()随机整数rng.integers(0, 10, size=(3, 4))

每个 NumPy 数组都有一些重要属性,了解它们是后续操作的基础:

import numpy as np
arr = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])
print(f"形状 (shape): {arr.shape}") # (3, 4) → 3 行 4 列
print(f"维度 (ndim): {arr.ndim}") # 2 → 二维数组
print(f"元素总数 (size): {arr.size}") # 12 → 3 × 4 = 12
print(f"数据类型 (dtype): {arr.dtype}") # int64
print(f"每个元素字节数: {arr.itemsize}") # 8 → int64 占 8 字节
print(f"总字节数: {arr.nbytes}") # 96 → 12 × 8 = 96

shape 是最常用的属性,它告诉你数组的”形状”:

# 一维数组
a = np.array([1, 2, 3])
print(a.shape) # (3,) → 3 个元素
# 二维数组
b = np.array([[1, 2, 3], [4, 5, 6]])
print(b.shape) # (2, 3) → 2 行 3 列
# 三维数组
c = np.ones((2, 3, 4))
print(c.shape) # (2, 3, 4) → 2 个 "3行4列的矩阵"

理解 shape 的方式:从外到内,逐层数

三维数组 shape = (2, 3, 4)
↓ ↓ ↓
│ │ └── 最内层:每行 4 个元素
│ └───── 中间层:每个矩阵 3 行
└──────── 最外层:共 2 个矩阵

NumPy 数组中所有元素必须是同一类型。这也是它能快速运算的关键。

dtype含义示例值常见场景
int3232位整数-2147483648 ~ 2147483647计数、索引
int6464位整数(默认)更大范围通用整数
float3232位浮点数约7位有效数字深度学习(节省显存)
float6464位浮点数(默认)约15位有效数字科学计算(高精度)
bool布尔值True / False条件过滤
str_字符串”hello”文本标签(少用)
# 自动推断类型
a = np.array([1, 2, 3]) # int64(全是整数)
b = np.array([1.0, 2.0, 3.0]) # float64(有小数点)
c = np.array([1, 2.5, 3]) # float64(混合时自动向上转)
# 手动指定类型
d = np.array([1, 2, 3], dtype=np.float32)
print(d) # [1. 2. 3.]
print(d.dtype) # float32
e = np.zeros(5, dtype=np.int32)
print(e) # [0 0 0 0 0]
print(e.dtype) # int32
# 整数转浮点数
int_arr = np.array([1, 2, 3, 4])
float_arr = int_arr.astype(np.float64)
print(float_arr) # [1. 2. 3. 4.]
print(float_arr.dtype) # float64
# 浮点数转整数(直接截断,不是四舍五入!)
float_arr2 = np.array([1.7, 2.3, 3.9])
int_arr2 = float_arr2.astype(np.int32)
print(int_arr2) # [1 2 3] ← 注意:3.9 变成了 3,不是 4!
# 布尔转换
bool_arr = np.array([0, 1, 0, 2, -1]).astype(bool)
print(bool_arr) # [False True False True True] ← 0 是 False,非 0 是 True

float32 vs float64:什么时候用哪个?

Section titled “float32 vs float64:什么时候用哪个?”
# float64:默认,精度高
a = np.array([1.0, 2.0, 3.0]) # 默认 float64,每个元素 8 字节
# float32:省内存,深度学习常用
b = np.array([1.0, 2.0, 3.0], dtype=np.float32) # 每个元素 4 字节
# 内存对比
rng = np.random.default_rng(seed=42)
big_f64 = rng.random(1_000_000) # float64
big_f32 = rng.random(1_000_000).astype(np.float32) # float32
print(f"float64 占内存: {big_f64.nbytes / 1024 / 1024:.1f} MB") # 7.6 MB
print(f"float32 占内存: {big_f32.nbytes / 1024 / 1024:.1f} MB") # 3.8 MB

有时候你需要基于已有数组的形状创建新数组:

original = np.array([[1, 2, 3], [4, 5, 6]])
# 创建和 original 形状相同的全 0 数组
z = np.zeros_like(original)
print(z)
# [[0 0 0]
# [0 0 0]]
# 创建和 original 形状相同的全 1 数组
o = np.ones_like(original)
print(o)
# [[1 1 1]
# [1 1 1]]
# 创建和 original 形状相同的指定值数组
f = np.full_like(original, 99)
print(f)
# [[99 99 99]
# [99 99 99]]
# 创建未初始化的数组(快但值随机)
e = np.empty_like(original)
# ⚠️ 值是随机的,不要直接使用未赋值的 empty 数组!

学完这一页,至少保留这张证据卡:

数组状态
操作前的形状、dtype、轴和样本值
操作
索引、切片、广播、reshape、线性代数,或随机/统计函数
输出
结果数组形状、值,或统计量
失败检查
轴混淆、视图/副本陷阱、广播不匹配或形状错误
期望产出
打印的形状和值,便于检查数组运算
root((NumPy 数组基础))
创建数组
np.array 从列表创建
np.zeros / ones / full
np.arange / linspace
rng.random / standard_normal / integers
np.eye 单位矩阵
数组属性
shape 形状
ndim 维度
size 元素总数
dtype 数据类型
数据类型
int32 / int64
float32 / float64
bool
astype 类型转换

import numpy as np
# 1. 创建一个包含 1 到 20 的一维数组
arr1 = np.arange(1, 21)
# 2. 创建一个 4×5 的全零矩阵
arr2 = np.zeros((4, 5))
# 3. 创建一个 3×3 的矩阵,所有元素为 7
arr3 = np.full((3, 3), 7)
# 4. 创建一个从 0 到 2π (np.pi * 2) 之间均匀分布的 100 个点
arr4 = np.linspace(0, np.pi * 2, 100)
# 5. 创建一个 5×5 的随机整数矩阵(范围 1~50)
rng = np.random.default_rng(seed=42)
arr5 = rng.integers(1, 51, size=(5, 5))

创建一个 shape 为 (3, 4, 5) 的全 1 数组,回答以下问题:

  1. 它的维度(ndim)是多少?
  2. 它有多少个元素(size)?
  3. 默认的 dtype 是什么?
  4. 把它转换成 int32 类型后,每个元素占多少字节?
# 给定考试成绩(浮点数)
scores = np.array([85.6, 92.3, 78.8, 95.1, 60.5, 73.9])
# 1. 把成绩四舍五入到整数
rounded = np.rint(scores).astype(int)
# 2. 判断每个成绩是否及格(>= 60),得到布尔数组
passed = scores >= 60
# 3. 计算及格人数(提示:True 算 1,False 算 0)
pass_count = passed.sum()
参考实现与讲解
  • 形状检查应当是 arr1.shape == (20,)arr2.shape == (4, 5)arr3.shape == (3, 3)arr4.shape == (100,)arr5.shape == (5, 5)
  • np.ones((3, 4, 5)) 是 3 维数组,共 60 个元素。没有指定 dtype 时,NumPy 通常使用 float64int32 数组的 itemsize 是 4 字节。
  • 成绩数组可以用四舍五入得到更像整数的展示结果,但及格人数要按原始规则计算,例如 scores >= 60,所以 60.5 应当算及格。