HOWTO · NumPy

将矩阵转换为 NumPy 数组

本教程演示了如何在 python 中将矩阵转换为数组

本页内容

使用 np.asarray() 或 np.array() 将矩阵转换为 NumPy ndarray,同时保留其维度。若要得到一维结果,可对数组调用 flatten()、ravel() 或 reshape(-1)。之后修改结果时,选择哪种方法很重要:flatten() 总会创建副本;如果内存布局允许,ravel() 和 reshape(-1) 则可能与源数据共享内存。

下面的示例从一个由列表组成的 Python 列表开始,将其转换为数组,并比较三种生成一维数组的方法。示例还展示了修改一维结果时源数组会发生什么。此示例已执行;输出显示了保留的二维形状,以及对展平副本所做的修改。

将矩阵转换为二维 NumPy 数组

对于嵌套列表,np.asarray(matrix) 会创建一个形状相同的二维数组。np.array(matrix) 也是一种直接的转换方式。这两种调用都会根据嵌套结构推断维度;它们都不会将数组展平。对于已有的 ndarray,如果无需转换,np.asarray() 可以直接返回该数组;而 np.array() 默认会创建副本。如果需要独立数组,可以使用后一种方法;也可以在所用 NumPy 版本支持时传入 copy=True,明确表达这一意图。

运行下面的示例:

本节中的代码以及显示的标签或输出仍为英文。

import numpy as np

matrix = [[1, 2, 3], [4, 5, 6]]
array = np.asarray(matrix)
flat_copy = array.flatten()
flat_view_when_possible = array.ravel()
flat_reshape_when_possible = array.reshape(-1)

print(array.shape)
print(array)
print(flat_copy)
print(flat_view_when_possible)
print(flat_reshape_when_possible)
flat_copy[0] = 99
print(array[0, 0], flat_copy[0])
(2, 3)
[[1 2 3]
 [4 5 6]]
[1 2 3 4 5 6]
[1 2 3 4 5 6]
[1 2 3 4 5 6]
1 99

第一个结果的形状是 (2, 3),因此仍是二维数组。后面的结果形状为 (6,),是一维数组。最后的赋值会修改展平后的副本,不会改变 array。该示例已成功执行,退出代码为 0。

将矩阵展平为一维数组

array.flatten() 会返回一维副本,因此修改其结果中的元素不会影响原数组。如果后续代码可能修改展平后的数据,而你又不希望源数组受到影响,这通常是一个合适的默认选择。

array.ravel() 也会生成一维数组。内存布局允许时,它会返回视图;如果数组的内存布局不允许创建视图,则会创建副本。np.ravel(array) 是对应的 NumPy 函数;array.ravel() 则是它的方法形式。由于是否共享数据取决于内存布局,除非已确认结果是视图,否则不要依赖通过 ravel() 的结果写入来更新源数组。

方法 array.reshape(-1) 会让 NumPy 根据元素数量推断一维形状。条件允许时,它可以返回视图;必要时也会创建副本。它改变的是结果的形状,不会改变本示例所要求的元素顺序。这三种方法默认都按 C 顺序展平;需要其他遍历顺序时,请指定 order 参数。

选择展平方法

需要独立副本并希望修改操作与源数组隔离时,选择 flatten()。想简洁地得到一维结果,并且可以接受它根据源数组布局共享内存或创建副本时,选择 ravel()。如果用形状变换来表达操作更符合周围代码的写法,可以选择 reshape(-1);它同样可能共享数据,也可能创建副本。

转换与展平解决的是不同问题。先用 np.asarray() 或 np.array() 获取 ndarray,同时保留二维形状。只有当后续函数需要一维序列时,才使用展平操作。如果必须保持源数据不变,请使用 flatten(),或在修改结果前显式创建副本。如果内存共享关系会影响性能或正确性,应检查数组之间的关系,不要假定每个 ravel() 或 reshape 操作都会返回视图。