一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

NumPy数组创建完全指南:从零搭建你的数字积木城

时间:2026-06-03 08:30:01 编辑:袖梨 来源:一聚教程网

在机器学习实践过程中,NumPy是一个绕不开的基础工具,它提供了高效的数组运算能力,是进行数据处理的必备技能。本指南将详细介绍如何从零开始创建NumPy数组,涵盖多种创建方式与实用技巧,帮助你快速掌握这一核心强项。

NumPy数组创建完全指南:从零搭建你的数字积木城


为什么要学NumPy?

将机器学习比作一场冒险旅行,那么NumPy就是出发前必须掌握的基础技能课程,其重要性不言而喻。

NumPy数组创建完全指南:从零搭建你的数字积木城

在处理Python数据时,你很可能见过这一行类似“神咒”的代码:

import numpy as np

如此受推崇的原因可以总结为两点:速度快操作简

  1. 向量化运算:告别繁复的for循环,用一行代码完成以前十行的工作。
  2. 广播机制:形状不同的数组也能直接进行运算,这是原生Python列表无法做到的。

本文将带你从数组创建变形运算,系统性地打牢NumPy基础——地基稳固,后续学习才能从容不迫。


一、np.array:从列表到数组,一步之遥

最直接的方式,就是将Python列表作为参数传入:

arr = np.array([1, 2, 3])
print(arr)  # [1 2 3]

可能会有人问,Python列表[1, 2, 3]也能用,为什么需要多此一举?

因为它们本质上是不同的数据类型:

Python列表NumPy数组
类型可以容纳多种类型,例如int、str、dict可以混装类型统一,一个数组只能包含一种数据类型
运算[1,2]+[3,4] 结果为 [1,2,3,4](拼接操作)np.array([1,2])+np.array([3,4]) 结果为 [4 6](逐元素相加)
速度依赖于循环处理,速度较慢底层采用C语言实现,计算速度极快
# Python列表:+ 代表拼接
[1, 2, 3] + [4, 5, 6]  # [1, 2, 3, 4, 5, 6]# NumPy数组:+ 代表数学运算
np.array([1, 2, 3]) + np.array([4, 5, 6])  # [5 7 9]

简单来说,列表侧重于“存储数据”,而数组侧重于“运算数据”。两者功能不同,不能混淆使用。


二、嵌套列表:给积木加个维度

一维数组像一条线,二维数组像一张表,三维数组则像一个立体箱子。通过嵌套列表可以逐层构建更高维度的结构:

list1 = [list(range(i, i+3)) for i in [2, 4, 6]]
print(list1)
# [[2, 3, 4], [6, 7, 8], [10, 11, 12]]c = np.array([range(i, i+3) for i in [2, 4, 6]])
print(c)
# [[ 2  3  4]
#  [ 6  7  8]
#  [10 11 12]]

每一层嵌套的列表就相当于结构的一个层级,层层叠加就能形成立体化的数据组织方式,其原理非常直观。


三、快速创建:NumPy的"模板工厂"

有些数组不需要手动逐一填充数值——全零、全一、等差数列等,NumPy已经预先准备好了相应的创建函数。

np.zeros:全0数组

nz = np.zeros(10, dtype=int)
print(nz)  # [0 0 0 0 0 0 0 0 0 0]

这行代码生成了十个零,排列整齐。指定dtype=int可以确保输出整数类型而非浮点数。

np.ones:全1数组

no = np.ones((3, 5))
print(no)
# [[1. 1. 1. 1. 1.]
#  [1. 1. 1. 1. 1.]
#  [1. 1. 1. 1. 1.]]

生成一个3行5列的全一数组,默认数据类型是浮点型(1.而非1)。如果需要整数,可以添加dtype=int参数。

np.arange:等差数列

该函数与Python内置的range功能相似,但直接返回NumPy数组:

na = np.arange(0, 20, 2)
print(na)  # [ 0  2  4  6  8 10 12 14 16 18]

对比两者:

list(range(0, 20, 2))  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] ← 列表类型
np.arange(0, 20, 2)    # [ 0  2  4  6  8 10 12 14 16 18] ← 数组类型

虽然输出外观相似,但底层实现完全不同。一个是Python对象列表,另一个是NumPy的连续内存块。


四、随机数组:开盲盒时间

随机数生成是NumPy中一个有趣的功能——每次生成的结果都可能不同(除非设置了固定的随机种子)。

基础随机

a1 = np.random.random()           # 单个[0,1)区间的随机浮点数
a2 = np.random.random(1)          # 包含一个元素的数组
a3 = np.random.random((3, 3))     # 生成3×3的随机数组
a4 = np.random.random((2, 3, 4))  # 生成2层×3行×4列的三维随机数组

指定范围

a5 = np.random.uniform(5, 7, (2, 2))  # [5,7)区间内的随机浮点数,2×2大小
a6 = np.random.randint(5, 7, (2, 2))  # [5,7)区间内的随机整数,2×2大小

uniform函数负责生成浮点随机数,randint负责生成整数随机数,它们的参数格式保持一致。

正态分布

正态分布的核心特点是:多数数据集中在均值附近,向两侧延伸则逐渐稀疏。人的身高、考试成绩、测量误差等许多自然现象都近似服从这个分布。

# 均值为0,标准差为1,生成3×3的正态分布随机数组
np.random.normal(0, 1, (3, 3))# 简化版:标准正态分布
np.random.randn(3, 3)

种子:给随机数写剧本

计算机生成的随机数实际上是“伪随机”——由特定算法按固定规则计算得出。设置种子可以将计算规则固定下来,保证每次运行得到完全相同的结果。

np.random.seed(0)
a = np.random.random(3)
print(a)  # 每次运行都会输出相同的值

何时需要设置种子?在代码调试阶段。如果你的程序出现错误,需要复现问题来分析原因,就必须确保输入数据不变。种子机制就像游戏的“存档点”,帮助你在相同的条件下重复实验。


五、特殊数组:预制件

np.eye:单位矩阵

ne = np.eye(3)
print(ne)
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

主对角线上的元素为1,其余位置均为0。在线性代数中,单位矩阵是“乘法单位元”——任何矩阵与其相乘,结果保持不变。

np.empty:未初始化的数组

ney = np.empty(3)
print(ney)  # 输出的值是内存中的残留数据,不确定

使用np.empty就像打开一个未知内容的盒子——你无法预知里面会有什么数值。但它的创建速度极快,因为它跳过了初始化步骤,适合用于后期会逐个赋值的场景。


六、数组属性:读懂你的积木

数组创建后,如何了解其结构?可以通过查看其属性:

x = np.random.randint(10, size=(3, 4, 5))  # 3层×4行×5列
属性含义本例值
ndim维度数量3
shape每个维度的大小(3, 4, 5)
size元素总个数60
dtype数据类型int64
itemsize单个元素占用的字节数8
nbytes占用的总字节数480
print('维度:', x.ndim)       # 3
print('形状:', x.shape)      # (3, 4, 5)
print('大小:', x.size)       # 60
print('类型:', x.dtype)      # int64

需要记住的关系式:nbytes = itemsize × size


七、切片:精准取值,小心副作用

切片是NumPy最常用的操作之一,但有一个需要特别注意的地方:切片返回的是视图,而非数据的副本

x = np.array([[3, 5, 2, 4],
              [7, 6, 8, 8],
              [1, 6, 7, 7]])x_sub = x[:2, :2]  # 选取前两行、前两列
print(x_sub)
# [[3 5]
#  [7 6]]

视图的含义是:当你修改切片的数据时,原数组中的数据也会随之改变。

x_sub[0, :] = 9
print(x_sub)  # [[9 9] [7 6]]
print(x)      # 原数组也被同步修改了!
# [[9 9 2 4]
#  [9 9 8 8]
#  [1 6 7 7]]

这就像你透过窗户观察房间——你在窗外摆放了一个花瓶,发现房间内也凭空多了一个。

如果需要独立操作切片数据,应该使用.copy()方法:

x_sub_copy = x[:2, :2].copy()
x_sub_copy[0, :] = 1
print(x)             # 原数组不受影响
print(x_sub_copy)    # 副本独立变化

这相当于给原数据拍了一张照片,对照片的修改不会影响真实的场景。


八、变形:reshape与newaxis

reshape:改变形状,不改内容

grid = np.arange(1, 10)           # [1 2 3 4 5 6 7 8 9]
grid_reshape = grid.reshape((3, 3))
print(grid_reshape)
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]

9个元素可以重新排列成3×3的矩阵,但无法变成4×3——因为元素总数必须保持不变

np.newaxis:增加一个维度

将一维数组转换为二维数组,本质是通过None插入一个长度为1的新维度:

x = np.array([1, 2, 3, 4, 5])# 变成一行(1×5)
x.reshape(1, 5)       # [[1 2 3 4 5]]
x[np.newaxis, :]      # 效果相同# 变成一列(5×1)
x.reshape(5, 1)       # [[1] [2] [3] [4] [5]]
x[:, np.newaxis]      # 效果相同

何时需要使用?当进行矩阵运算需要维度对齐的时候。例如,一个形状为(5,)的向量需要与一个形状为(3,5)的矩阵进行运算,首先需要将向量变为(1,5)的二维形状。


九、拼接与分裂:合体与分身

拼接:多个变一个

x = np.array([1, 2, 3])
y = np.array([3, 2, 1])
z = np.array([99, 99, 99])# 一维数组拼接
np.concatenate([x, y, z])  # [ 1  2  3  3  2  1 99 99 99]

二维数组则需要指定拼接方向:

grid = np.array([[1, 2, 3],
                 [4, 5, 6]])# axis=0:沿行方向上下堆叠
np.concatenate([grid, grid])
# [[1 2 3]
#  [4 5 6]
#  [1 2 3]
#  [4 5 6]]# axis=1:沿列方向左右拼接
np.concatenate([grid, grid], axis=1)
# [[1 2 3 1 2 3]
#  [4 5 6 4 5 6]]

NumPy还提供了两个快捷函数:

np.vstack([x, y, z, grid])  # 垂直堆叠,等价于axis=0
np.hstack([grid, grid])      # 水平堆叠,等价于axis=1

分裂:一个变多个

x = [0, 1, 2, 3, 4, 5, 6, 7, 8]
x1, x2, x3 = np.split(x, [3, 5])
print(x1, x2, x3)  # [0 1 2] [3 4] [5 6 7 8]

分裂规则:np.split(数组, [断点位置列表]),设定N个断点可以分割出N+1个子数组。

二维数组的分裂:

grid = np.arange(16).reshape(4, 4)# 垂直分割:按行划分
upper, lower = np.vsplit(grid, [2])# 水平分割:按列划分
left, right = np.hsplit(grid, [1])

十、通用函数:向量化的魔法

NumPy的运算允许直接对整个数组进行操作,无需编写for循环——这就是向量化的核心优势。

x = np.arange(4)
print('x     =', x)
print('x + 5 =', x + 5)           # [5 6 7 8]
print('x - 5 =', x - 5)           # [-5 -4 -3 -2]
print('x * 2 =', x * 2)           # [0 2 4 6]
print('x / 2 =', x / 2)           # [0.  0.5 1.  1.5]
print('x // 2 =', x // 2)         # [0 0 1 1]  整除取商
print('x % 2 =', x % 2)           # [0 1 0 1]  余数
print('x ** 2 =', x ** 2)         # [0 1 4 9]  幂运算
print('-x     =', -x)              # [0 -1 -2 -3]

每种运算都有对应的函数形式:np.addnp.subtractnp.multiplynp.dividenp.power……

绝对值

x = np.array([-2, -1, 0, 1, 2])
print(np.abs(x))           # [2 1 0 1 2]
print(np.absolute(x))      # 效果相同

复数的模

y = np.array([3 - 4j, 4 - 3j, 2 + 0j, 0 + 1j])
print(abs(y))  # [5. 5. 2. 1.]

对复数取绝对值,返回的是其模长——即实部与虚部的平方和再开根号。例如3-4j的模就是√(9+16)=5



写在最后

回顾一下今天搭建的“积木”知识体系:

  1. 基础创建np.array 实现从列表到数组的快速转换,zeros/ones/arange 用于快速生成标准模板
  2. 随机数组randomuniformnormal 各有不同用途,seed 是调试过程中的“存档点”
  3. 变形与操作reshape 改变数组形状、切片返回数据视图、拼接分裂实现数据组合
  4. 向量化运算:告别 for 循环,用单行代码完成批量计算

数组创建是 NumPy 学习道路的起点,而非终点。你可以将上面的速查表收藏备用,接下来可以继续探索以下内容:

  1. 索引与切片进阶 — 包括花式索引、布尔索引等高级技巧
  2. 广播机制 — 不同形状数组进行对齐运算的原理
  3. 线性代数 — 矩阵乘法、特征值分解等线性代数操作
  4. 实战项目 — 运用 NumPy 进行图像处理、数据分析等实际应用

速查表

场景函数一句话说明
从列表创建np.array()最基础的创建方式,可接受任意嵌套列表
全零np.zeros()用于初始化占位
全一np.ones()同上
等差数列np.arange()类似range函数,但直接返回数组
随机浮点np.random.random()[0,1)区间内
指定范围随机np.random.uniform()自定义数值区间
随机整数np.random.randint()整数版本
正态分布np.random.normal()高斯分布
固定种子np.random.seed()使随机结果可重现
单位矩阵np.eye()对角线为1,其余为0
未初始化np.empty()创建速度快,但值不确定
变形reshape改变形状但不改变数据内容
加维度np.newaxis将一维数组变为二维
拼接concatenate/vstack/hstack多个数组合并为一个
分裂split/vsplit/hsplit一个数组分割为多个

经过本次学习,你已经掌握了 NumPy 数组创建的核心技巧,可以在此基础上进行更深入的数据分析工作。

热门栏目