讲师中心 微信公众号
AI工具推荐 视频效率加速

NumPy教程:在循环中高效构建多维数组

大浩小哥_7956

大浩小哥_7956

发布时间:2025-09-22 12:37:34

|

584人浏览过

|

来源于php中文网

原创

numpy教程:在循环中高效构建多维数组

本教程旨在解决在循环中迭代地将多个二维NumPy数组(例如(10, 3))组合成一个更高维度的父数组(例如(X, 10, 3))的常见问题。我们将探讨传统方法为何可能不适用,并提供一个NumPy原生的高效解决方案,通过巧妙地扩展子数组的维度,结合np.vstack或np.concatenate实现目标,避免了不必要的维度增加或性能开销。

1. 理解问题:迭代构建多维数组的挑战

在数据处理和机器学习的场景中,我们经常会遇到需要在一个循环中收集并组合多个具有相同形状的NumPy数组。例如,我们可能有一系列形状为 (10, 3) 的子数组,希望将它们累积到一个最终的父数组中,使其形状变为 (X, 10, 3),其中 X 是子数组的数量。

直接使用 np.stack() 或 np.concatenate() 在循环中进行迭代操作时,可能会遇到一些不符合预期的行为:

  • np.stack() 的问题: np.stack() 的作用是在一个新的轴上连接数组。如果在循环中重复使用 np.stack(),它会在每次迭代时都创建一个新的轴,导致最终数组的维度不断增加,而不是我们期望的在第一个轴上进行堆叠。例如,将 (10, 3) 堆叠到 (1, 10, 3) 上,再堆叠会得到 (1, 1, 10, 3),而非 (2, 10, 3)。
  • np.concatenate() 的问题: np.concatenate() 默认沿着现有轴连接数组。如果直接将 (10, 3) 数组连接到一个 (X, 10, 3) 数组上,NumPy会尝试匹配维度,这通常会导致错误,除非我们显式地调整子数组的维度。

一个常见的“工作区”解决方案是先将所有子数组收集到一个标准的Python列表中,然后在循环结束后,一次性地使用 np.array(list_of_arrays) 将列表转换为NumPy数组。这种方法虽然有效,但在处理大量数据时,可能会引入额外的内存开销和类型转换的性能损耗,因为它需要先构建Python列表,然后再转换为NumPy数组。

import numpy as np

# 示例子数组
arr1 = np.random.rand(10, 3)
arr2 = np.random.rand(10, 3)
arr3 = np.random.rand(10, 3)

# 常见的列表-转换方法
list_of_arr = []
list_of_arr.append(arr1)
list_of_arr.append(arr2)
list_of_arr.append(arr3)

parent_array_from_list = np.array(list_of_arr)
print("使用列表转换得到的数组形状:", parent_array_from_list.shape)
# 预期输出: (3, 10, 3)

虽然列表转换方法可行,但NumPy提供了更直接、更“原生”的方式来处理这类迭代构建任务。

2. NumPy解决方案:维度扩展与垂直堆叠

解决上述问题的关键在于,在每次迭代中,将要添加的子数组的维度进行扩展,使其与父数组的维度兼容,然后再进行连接。具体来说,我们需要将每个 (10, 3) 形状的子数组转换为 (1, 10, 3) 形状,然后使用 np.vstack() 或 np.concatenate(axis=0) 沿着第一个轴进行堆叠。

2.1 维度扩展 (np.newaxis 或 np.expand_dims)

NumPy提供了两种主要方式来在现有数组中添加新的维度:

  • np.newaxis: 这是一个特殊的索引对象,用于在指定位置插入新轴。当用作索引时,它会在该位置创建一个长度为1的新维度。
    arr = np.random.rand(10, 3)
    # 将 (10, 3) 变为 (1, 10, 3)
    arr_expanded = arr[np.newaxis, :]
    print("使用 np.newaxis 扩展后的形状:", arr_expanded.shape)
    # 预期输出: (1, 10, 3)
  • np.expand_dims(): 这是一个函数,可以更明确地指定在哪里添加新维度。
    arr = np.random.rand(10, 3)
    # 将 (10, 3) 变为 (1, 10, 3),在 axis=0 处添加新维度
    arr_expanded = np.expand_dims(arr, axis=0)
    print("使用 np.expand_dims 扩展后的形状:", arr_expanded.shape)
    # 预期输出: (1, 10, 3)

    这两种方法效果相同,都可以将 (10, 3) 数组转换为 (1, 10, 3) 数组,使其可以被“垂直”堆叠到另一个 (X, 10, 3) 数组上。

2.2 垂直堆叠 (np.vstack 或 np.concatenate(axis=0))

一旦子数组被扩展为 (1, 10, 3) 形状,我们就可以使用以下函数将其与现有的父数组进行连接:

Python Hardener
Python Hardener

通过完整的安全审查、代码整洁重构、健壮的错误处理、正确的日志记录以及完整的文档字符串覆盖,强化 Python 脚本。

下载
  • np.vstack(): 这个函数用于垂直堆叠(按行堆叠)数组。它要求所有输入数组的除了第一个轴以外的其他轴的长度都相同。对于形状为 (N, ...) 的数组,vstack 相当于 concatenate(axis=0)。
  • np.concatenate(axis=0): 这是一个更通用的连接函数,允许我们指定连接的轴。当 axis=0 时,它会沿着第一个轴(垂直方向)连接数组。
# 示例:初始化一个父数组
initial_arr = np.random.rand(10, 3)
# 首次使用时,也需要扩展维度
parent_array = initial_arr[np.newaxis, :]
print("初始父数组形状:", parent_array.shape) # (1, 10, 3)

# 模拟循环添加新的子数组
new_arr_1 = np.random.rand(10, 3)
new_arr_1_expanded = new_arr_1[np.newaxis, :]
parent_array = np.vstack((parent_array, new_arr_1_expanded))
print("添加一个子数组后父数组形状:", parent_array.shape) # (2, 10, 3)

new_arr_2 = np.random.rand(10, 3)
new_arr_2_expanded = np.expand_dims(new_arr_2, axis=0)
parent_array = np.concatenate((parent_array, new_arr_2_expanded), axis=0)
print("再添加一个子数组后父数组形状:", parent_array.shape) # (3, 10, 3)

3. 完整实现示例

下面是一个完整的代码示例,展示了如何在循环中迭代地将多个 (10, 3) 数组添加到 (X, 10, 3) 父数组中:

import numpy as np

# 为了结果的可复现性,设置随机种子
np.random.seed(0)

# 1. 初始化父数组
# 创建第一个 (10, 3) 形状的子数组
first_child_array = np.random.random((10, 3))

# 将其维度扩展为 (1, 10, 3),作为父数组的初始状态
# 可以使用 np.newaxis 或 np.expand_dims
parent_array = first_child_array[np.newaxis, :]
# 或者: parent_array = np.expand_dims(first_child_array, axis=0)

print("初始父数组形状:", parent_array.shape)
print("初始父数组内容:\n", parent_array)

# 2. 在循环中迭代添加更多子数组
num_iterations = 3 # 假设我们要添加3个额外的子数组

for i in range(num_iterations):
    # 生成一个新的 (10, 3) 形状的子数组
    # 在实际应用中,这可能是从文件读取、计算或其他来源获取的数据
    current_child_array = np.random.random((10, 3))

    # 将当前子数组的维度扩展为 (1, 10, 3)
    current_child_array_expanded = current_child_array[np.newaxis, :]
    # 或者: current_child_array_expanded = np.expand_dims(current_child_array, axis=0)

    # 使用 np.vstack 将扩展后的子数组垂直堆叠到父数组上
    parent_array = np.vstack((parent_array, current_child_array_expanded))
    # 或者使用 np.concatenate:
    # parent_array = np.concatenate((parent_array, current_child_array_expanded), axis=0)

    print(f"\n迭代 {i+1} 后父数组形状:", parent_array.shape)

print("\n最终父数组内容:\n", parent_array)
print("\n最终父数组形状:", parent_array.shape)
# 预期最终形状为 (1 + num_iterations, 10, 3) = (4, 10, 3)

输出示例(部分):

初始父数组形状: (1, 10, 3)
初始父数组内容:
 [[[0.5488135  0.71518937 0.60276338]
  [0.54488318 0.4236548  0.64589411]
  ...
  [0.94466892 0.52184832 0.41466194]]]

迭代 1 后父数组形状: (2, 10, 3)

迭代 2 后父数组形状: (3, 10, 3)

迭代 3 后父数组形状: (4, 10, 3)

最终父数组内容:
 [[[0.5488135  0.71518937 0.60276338]
  [0.54488318 0.4236548  0.64589411]
  ...
  [0.94466892 0.52184832 0.41466194]]

 [[0.26455561 0.77423369 0.45615033]
  [0.56843395 0.0187898  0.6176355 ]
  ...
  [0.2532916  0.46631077 0.24442559]]

 [[0.15896958 0.11037514 0.65632959]
  [0.13818295 0.19658236 0.36872517]
  ...
  [0.09394051 0.5759465  0.9292962 ]]

 [[0.07683907 0.0871293  0.0202184 ]
  [0.83261985 0.77815675 0.87001215]
  ...
  [0.97676109 0.60484552 0.73926358]]]

最终父数组形状: (4, 10, 3)

4. 注意事项与性能考量

  • 初始数组: 确保在循环开始前正确初始化父数组。如果循环次数 X 至少为1,则用第一个子数组扩展维度后作为初始父数组是常见的做法。如果 X 可能为0,则需要特殊处理,例如初始化为空数组并检查其形状。

  • 性能: 尽管 np.vstack 和 np.concatenate 比纯Python列表操作更高效,但在循环中重复地创建新数组并复制旧数据到新数组(这是 vstack 和 concatenate 在内部可能做的)仍然会带来一定的性能开销,尤其是在 X 非常大时。

  • 预分配: 如果你知道最终需要多少个子数组(即 X 的值是已知的),最高效的方法是预先分配一个足够大的NumPy数组,然后直接填充数据。

    # 假设已知总共有 num_total_arrays 个子数组
    num_total_arrays = 4
    # 预分配一个 (num_total_arrays, 10, 3) 的数组
    # 可以用 np.zeros, np.empty 或 np.full
    final_parent_array = np.zeros((num_total_arrays, 10, 3), dtype=np.float32)
    
    for i in range(num_total_arrays):
        # 生成或获取当前子数组
        current_child_array = np.random.random((10, 3)).astype(np.float32)
        # 直接填充到预分配数组的相应位置
        final_parent_array[i, :, :] = current_child_array
    
    print("\n预分配方法得到的最终数组形状:", final_parent_array.shape)

    预分配方法避免了在每次迭代中重新创建和复制数组,显著提高了性能。然而,如果 X 是未知且动态变化的,那么迭代地使用维度扩展和 np.vstack 仍然是一个简洁且NumPy友好的解决方案。

5. 总结

本教程介绍了在Python循环中,如何高效且正确地将多个相同形状的NumPy子数组迭代地组合成一个更高维度的父数组。核心方法是利用 np.newaxis 或 np.expand_dims 在每次迭代中为子数组添加一个新的维度,使其形状从 (N, M) 变为 (1, N, M),然后使用 np.vstack() 或 np.concatenate(axis=0) 将其垂直堆叠到父数组上。这种方法避免了 np.stack() 在迭代中产生额外维度的困扰,也比先收集到Python列表再转换的方式更具NumPy特性。对于已知最终数组大小的场景,预分配数组并直接填充数据是更优的性能选择。理解这些NumPy数组操作的细微差别,对于编写高效且健壮的科学计算代码至关重要。

热门AI工具

更多
VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6607

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2748

2023.08.10

C++类型转换方式
C++类型转换方式

本专题整合了C++类型转换相关内容,想了解更多相关内容,请阅读专题下面的文章。

2562

2025.07.15

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

0

2026.11.05

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

0

2026.11.05

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

0

2026.11.04

XORM框架结构体映射与表结构同步
XORM框架结构体映射与表结构同步

本专题围绕XORM框架的结构体映射展开,说明表名与字段的命名策略、xorm标签常用属性、主键自增与时间字段自动填充,并演示Sync2自动建表、增量字段升级、索引声明与反向生成结构体的完整流程。

0

2026.11.04

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

0

2026.11.04

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

0

2026.11.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn