0

0

python中numpy怎么改变数组的形状(reshape)?

冰火之心

冰火之心

发布时间:2025-09-22 17:02:01

|

782人浏览过

|

来源于php中文网

原创

NumPy中reshape()与resize()的核心差异在于:reshape()返回新形状的视图,不改变原数组,要求元素总数不变;resize()则原地修改数组,可改变元素数量,不足时填充0,多余时截断。

python中numpy怎么改变数组的形状(reshape)?

在Python中,NumPy数组改变形状(或者说重塑)最核心、最常用的方法是使用

reshape()
函数。它能够根据你指定的新维度,返回一个拥有相同数据但形状不同的新数组视图,而不会修改原始数组。

解决方案

当我们需要改变NumPy数组的形状时,

numpy.reshape()
方法是我们的首选工具。它的基本用法是接收一个元组作为参数,这个元组定义了你希望数组变成的新形状。

举个例子,假设你有一个一维数组,里面有12个元素,你想把它变成一个3行4列的二维数组:

import numpy as np

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
print("原始数组:", arr)
print("原始形状:", arr.shape) # 输出 (12,)

# 使用 reshape 改变形状
new_arr = arr.reshape((3, 4))
print("\n重塑后的数组:\n", new_arr)
print("新形状:", new_arr.shape) # 输出 (3, 4)

# 验证原始数组未被修改
print("\n原始数组(确认未修改):", arr)

这里需要注意的是,

reshape()
通常会返回一个视图(view),这意味着新数组和原数组共享底层数据。如果你修改了新数组,原数组的数据也会跟着改变,反之亦然。当然,如果无法返回视图(例如内存布局不连续),它可能会返回一个副本。

立即学习Python免费学习笔记(深入)”;

一个非常方便的特性是,你可以在新形状的元组中使用

-1
作为其中一个维度。NumPy会根据数组的总元素数量和其余维度自动推断出这个维度的大小。这在处理不确定其中一个维度时特别有用。

# 使用 -1 让 NumPy 自动推断维度
arr_2d = arr.reshape((2, -1)) # 变成2行,列数自动推断
print("\n使用 -1 重塑为 (2, -1):\n", arr_2d)
print("形状:", arr_2d.shape) # 输出 (2, 6)

arr_3d = arr.reshape((-1, 2, 2)) # 变成 x 层,每层2行2列
print("\n使用 -1 重塑为 (-1, 2, 2):\n", arr_3d)
print("形状:", arr_3d.shape) # 输出 (3, 2, 2)

但无论如何重塑,一个基本原则是:新形状的元素总数必须与原始数组的元素总数保持一致。否则,NumPy会抛出一个

ValueError

NumPy中
reshape()
resize()
方法的核心差异是什么?

说实话,刚开始接触NumPy时,我个人也常常会混淆

reshape()
resize()
这两个方法。它们听起来都像是“改变大小”,但实际操作起来,核心区别非常大,理解这一点对于避免一些意想不到的问题至关重要。

reshape()
方法,就像我们前面提到的,它的主要功能是返回一个具有新形状的数组视图,而不会修改原始数组。它要求新旧数组的元素总数必须严格相等。这使得
reshape()
成为一个非常“安全”的操作,因为它不会破坏你原有的数据结构,你总是可以得到一个新的、形状不同的数组,而原始数据保持不变。在数据分析和处理流程中,我们经常需要对数据进行不同维度的观察,
reshape()
的非破坏性使得它成为首选。

import numpy as np

original_arr = np.arange(6) # [0, 1, 2, 3, 4, 5]
reshaped_arr = original_arr.reshape((2, 3))

print("原始数组:", original_arr)
print("重塑后的数组:\n", reshaped_arr)

# 尝试修改重塑后的数组
reshaped_arr[0, 0] = 99
print("\n修改重塑后的数组后,原始数组:", original_arr) # 原始数组也会被修改,因为是视图

numpy.resize()
(无论是作为函数
np.resize()
还是数组方法
arr.resize()
)则完全不同。它的主要特点是原地修改数组的形状,并且可以改变数组的元素总数。如果新形状的元素总数大于原始数组,NumPy会用零来填充新增的部分;如果小于原始数组,则会截断多余的元素。这听起来可能很方便,但在实际使用中,它的“破坏性”往往需要我们更加小心。

# np.resize() 作为函数,返回一个新数组
arr_func_resize = np.arange(4) # [0, 1, 2, 3]
resized_by_func = np.resize(arr_func_resize, (3, 3)) # 元素总数从4变为9,会填充0
print("\n使用 np.resize() 函数重塑并填充:\n", resized_by_func)
print("原始数组(函数操作不影响):", arr_func_resize)

# arr.resize() 作为数组方法,原地修改
arr_method_resize = np.arange(4) # [0, 1, 2, 3]
print("\n原地修改前:", arr_method_resize)
arr_method_resize.resize((2, 3)) # 元素总数从4变为6,填充0
print("原地修改后:\n", arr_method_resize)

arr_method_truncate = np.arange(6) # [0, 1, 2, 3, 4, 5]
print("\n原地截断前:", arr_method_truncate)
arr_method_truncate.resize((2, 2)) # 元素总数从6变为4,截断
print("原地截断后:\n", arr_method_truncate)

在我看来,

resize()
方法更像是“改变数组的大小并适应新大小”,而
reshape()
更像是“在保持数据不变的前提下,重新组织数据的观察方式”。由于
resize()
会改变元素数量并原地修改,我个人在大部分情况下会倾向于使用
reshape()
,因为它更可控,不易产生副作用。只有当我明确需要改变数组大小并接受其填充或截断行为时,才会考虑
resize()

Elser AI Comics
Elser AI Comics

一个免费且强大的AI漫画生成工具,助力你三步创作自己的一出好戏

下载

在NumPy中,如何将任意维度的数组展平(flatten)为一维?

将多维数组展平为一维数组,是数据预处理和机器学习中非常常见的操作,比如在将图像数据输入到全连接层之前。NumPy提供了几种灵活的方式来实现这一点,每种方式都有其细微的差别和适用场景。

最直接也是我个人最常用的一种方式是结合

reshape()
-1
占位符:

  1. arr.reshape(-1)
    : 这是将数组展平为一维的最简洁方式。通过指定一个维度为
    -1
    ,NumPy会自动计算出这个维度的大小,而其他维度则被隐式地“压缩”掉。这种方法通常会返回一个视图,这意味着它不会复制数据,因此效率很高。

    import numpy as np
    
    matrix = np.array([[1, 2, 3],
                       [4, 5, 6]])
    print("原始矩阵:\n", matrix)
    
    flattened_by_reshape = matrix.reshape(-1)
    print("\n通过 reshape(-1) 展平:\n", flattened_by_reshape)
    print("形状:", flattened_by_reshape.shape)

除了

reshape(-1)
,NumPy还提供了两个专门用于展平的方法:

  1. arr.flatten()
    : 这个方法会返回一个新的数组副本,其中包含了原始数组的所有元素,并以一维形式排列。由于它创建了一个副本,对展平后的数组的修改不会影响原始数组。这在你需要独立操作展平数据而不想影响原数据时非常有用。它默认以C-order(行优先)进行展平,但你可以通过
    order
    参数指定为F-order(列优先)。

    flattened_by_flatten = matrix.flatten()
    print("\n通过 flatten() 展平 (副本):\n", flattened_by_flatten)
    flattened_by_flatten[0] = 99 # 修改副本
    print("修改副本后:", flattened_by_flatten)
    print("原始矩阵(未受影响):\n", matrix)
    
    # 以F-order展平
    flattened_f_order = matrix.flatten(order='F')
    print("\n通过 flatten() 以 F-order 展平:\n", flattened_f_order)
  2. arr.ravel()
    ravel()
    方法与
    flatten()
    非常相似,它也返回一个一维数组。但关键区别在于,
    ravel()
    会尽可能地返回一个视图。只有当无法创建视图(例如,数组不是C-contiguous或F-contiguous时),它才会返回一个副本。这意味着
    ravel()
    在大多数情况下比
    flatten()
    更高效,因为它避免了数据复制。与
    flatten()
    一样,它也支持
    order
    参数。

    flattened_by_ravel = matrix.ravel()
    print("\n通过 ravel() 展平 (视图或副本):\n", flattened_by_ravel)
    flattened_by_ravel[0] = 100 # 如果是视图,原始矩阵会改变
    print("修改 ravel() 结果后:", flattened_by_ravel)
    print("原始矩阵(可能受影响):\n", matrix) # 这里的 matrix 会变成 [[100, 2, 3], [4, 5, 6]]

在我个人实践中,如果我需要一个独立的数据副本,我可能会明确使用

flatten()
。但如果我只是想以一维方式处理数据,并且不介意它是一个视图(或者知道我不会修改它),那么
reshape(-1)
ravel()
通常是更高效的选择。特别是在处理大型数据集时,避免不必要的数据复制可以显著提升性能。

NumPy数组形状操作中常见的错误与规避策略有哪些?

在NumPy中进行数组形状操作时,虽然看似简单,但一些常见的陷阱可能会让人头疼。理解这些错误并掌握规避策略,能帮助我们更顺畅地处理数据。

  1. 元素总数不匹配(

    ValueError
    这是最常见也最直接的错误。当你尝试将一个数组重塑成一个新的形状,但新形状所能容纳的元素总数与原始数组的元素总数不一致时,NumPy会抛出
    ValueError: cannot reshape array of size X into shape Y

    import numpy as np
    
    arr = np.arange(10) # 10个元素
    # 错误示例:尝试重塑为 (3, 3),只有9个元素空间
    try:
        arr.reshape((3, 3))
    except ValueError as e:
        print(f"\n捕获到错误: {e}")

    规避策略

    • 检查元素总数:在重塑之前,始终确保
      arr.size
      (原始数组的元素总数)与你目标形状的乘积相等。例如,
      np.prod(new_shape)
    • 使用
      -1
      占位符
      :如果有一个维度的大小不确定,使用
      -1
      让NumPy自动计算,这样可以避免手动计算错误。这是我个人最喜欢也最常用的方法,可以大幅减少这类错误。
  2. 视图(View)与副本(Copy)的混淆 如前所述,

    reshape()
    ravel()
    通常返回视图,而
    flatten()
    返回副本。如果你不清楚这一点,可能会导致原始数据被意外修改,或者在预期修改副本时却修改了原始数据。

    original = np.array([[1, 2], [3, 4]])
    reshaped_view = original.reshape(-1)
    flattened_copy = original.flatten()
    
    reshaped_view[0] = 99 # 修改视图
    print("\n修改视图后,原始数组:", original) # original 变成了 [[99, 2], [3, 4]]
    
    flattened_copy[0] = 88 # 修改副本
    print("修改副本后,原始数组:", original) # original 仍然是 [[99, 2], [3, 4]]

    规避策略

    • 明确何时需要副本:如果你需要一个独立的数据集进行操作,而不影响原始数据,请显式地使用
      .copy()
      方法,或者选择
      flatten()
    • 理解操作的返回值:记住
      reshape()
      ravel()
      倾向于返回视图,而
      flatten()
      返回副本。当不确定时,可以通过
      arr.base is None
      来判断一个数组是否是另一个数组的视图(如果是视图,
      base
      会指向原始数组)。
  3. 内存布局(C-order vs. F-order)的影响 NumPy数组在内存中可以是行优先(C-order,默认)或列优先(F-order)存储。在大多数情况下,这不会直接导致错误,但在进行重塑时,特别是从一个维度跳到另一个维度时,它会影响元素的读取顺序。如果你从其他语言(如MATLAB)或库中获取数据,这可能会导致数据的意外排列。

    arr_c = np.arange(6).reshape((2, 3), order='C')
    arr_f = np.arange(6).reshape((2, 3), order='F')
    
    print("\nC-order 数组:\n", arr_c)
    print("F-order 数组:\n", arr_f)
    
    # 尝试将 F-order 数组重塑为不同形状,可能会导致元素顺序的误解
    reshaped_from_f = arr_f.reshape((3, 2), order='C') # 以C-order方式重塑
    print("\n从 F-order 数组以 C-order 重塑:\n", reshaped_from_f)

    规避策略

    • 保持一致性:尽可能在整个数据处理流程中保持一致的内存顺序。
    • 明确指定
      order
      参数
      :在
      reshape()
      flatten()
      ravel()
      中,你可以使用
      order='C'
      (默认)或
      order='F'
      来明确指定元素的读取顺序。当与外部数据交互或需要特定性能优化时,这尤其重要。
    • np.ascontiguousarray()
      :如果你需要确保数组是C-contiguous的,可以使用这个函数来创建一个副本。
  4. resize()
    的潜在副作用 前面已经提到,
    resize()
    会原地修改数组,并可能改变元素总数(填充或截断)。如果在不恰当的时候使用它,比如在函数内部对传入的数组进行
    resize
    操作,可能会对函数外部的原始数组造成意料之外的修改。

    规避策略

    • 优先使用
      reshape()
      :除非你明确需要原地修改并接受元素数量的改变,否则优先使用非破坏性的
      reshape()
    • 谨慎使用
      arr.resize()
      :如果你确实需要
      resize
      的功能,请确保你清楚它将如何影响你的数据,并且这正是你想要的行为。在函数内部,如果需要改变数组大小,通常更好的做法是创建一个新数组并返回。

在我看来,掌握这些规避策略,特别是对视图与副本的理解,以及善用

-1
占位符,可以大大提高我们使用NumPy进行数据处理的效率和代码的健壮性。这些细节虽然小,但往往是导致bug的根源。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

765

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

639

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

764

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

619

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1285

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

549

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

709

2023.08.11

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 6.1万人学习

Django 教程
Django 教程

共28课时 | 3.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号