"The reshape function returns its argument with a modified shape, whereas the ndarray.resize method



在 Numpy 中,reshape 函数使用修改后的形状返回其参数,而 ndarray.resize 方法修改数组本身。但这到底意味着什么?真正的区别是什么?

import numpy as np
a = np.arange(18)
b = a.reshape(3,6)
a.resize(3,6)
a[0] = -2
print(a)
[[-2 -2 -2 -2 -2 -2]
[ 6  7  8  9 10 11]
[12 13 14 15 16 17]]
print(b)
[[-2 -2 -2 -2 -2 -2]
[ 6  7  8  9 10 11]
[12 13 14 15 16 17]]
b[0]= -1
print(b)
[[-1 -1 -1 -1 -1 -1]
[ 6  7  8  9 10 11]
[12 13 14 15 16 17]]
print(a)
[[-1 -1 -1 -1 -1 -1]
[ 6  7  8  9 10 11]
[12 13 14 15 16 17]]

从上面的代码中,resize() 和 reshape() 对相同的数据执行相同的操作。为什么需要其中两个?

In [15]: a = np.arange(18) 
...: b = a.reshape(3,6)  

我喜欢用以下命令检查数组的属性:

In [16]: a.__array_interface__                                                                               
Out[16]: 
{'data': (65611776, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (18,),
'version': 3}
In [17]: b.__array_interface__                                                                               
Out[17]: 
{'data': (65611776, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (3, 6),
'version': 3}

请注意,两者的data相同。baview。 它是一个新的数组对象,但它共享基础数据缓冲区。 它的形状不同,但对a的变化将显示为b的变化(反之亦然)。

查看有关viewcopy的文档。 这是numpy的一个重要区别,所以你需要很好地理解它。

有时reshape必须返回副本,例如更改order。 同样重要的是要认识到reshape不能改变元素的数量。

还有一个reshape函数,在大多数情况下与该方法相同。

shape属性也可以直接更改:

In [19]: a.shape = (6,3)                                                                                     
In [20]: a                                                                                                   
Out[20]: 
array([[ 0,  1,  2],
[ 3,  4,  5],
[ 6,  7,  8],
[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]])
In [21]: b                                                                                                   
Out[21]: 
array([[ 0,  1,  2,  3,  4,  5],
[ 6,  7,  8,  9, 10, 11],
[12, 13, 14, 15, 16, 17]])

该操作已就地修改a本身。 它比reshape更严格一些,并且不经常使用。 例如,我们可以用一行b

b = np.arange(18).reshape(3,6)

resize的主要区别在于它可以更改元素的数量。 它可以截断,也可以增加大小。resize方法和函数都执行此操作,但具有不同的"填充"规则。resize方法就地运行。

在您的示例中,a.resize(3,6)就地更改了a,更改了其shape,但没有更改其数据缓冲区或b到该缓冲区的链接。 所以对a的变化也表现为b的变化。

就地shape更改后的a仍然具有相同的data

In [22]: a.__array_interface__                                                                               
Out[22]: 
{'data': (65611776, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (6, 3),
'version': 3}

以及resize方法后的相同data

In [23]: a.resize(3,6)                                                                                       
In [24]: a.__array_interface__                                                                               
Out[24]: 
{'data': (65611776, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (3, 6),
'version': 3}

请注意,如果我尝试以更改元素总数的方式resizea,则会出现错误。 那是因为b共享数据缓冲区,我们无法在不影响b大小的情况下更改a的大小。

In [28]: a.resize(4,6)                                                                                       
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-28-f7d47a627631> in <module>
----> 1 a.resize(4,6)
ValueError: cannot resize an array that references or is referenced
by another array in this way.
Use the np.resize function or refcheck=False

我想你会发现np.reshapea.reshape被使用了很多。 这两种形式的resize几乎都不经常使用。reshape更可预测、更安全。resize也可以做同样的事情,但它也可以让你做危险的事情。

我将专注于了解viewcopy之间的区别,其次是创建新数组和就地更改之间的区别。

这意味着一个函数将修改数组,而您只会拥有修改后的数组。

另一个将返回一个新数组,修改后,但保留原始数组不变。它将使用双倍的内存,但原始数组将可用于其他计算。

根据具体情况,您可能更喜欢其中一种。

我认为这最好通过示例来解释。

import numpy as np
a = np.arange(18)
b = a
print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17]
print(b)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17]
print("Reshape - doesnt change the base array")
print(a.reshape(3,6))
#[[ 0  1  2  3  4  5]
# [ 6  7  8  9 10 11]
# [12 13 14 15 16 17]]
print(b)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17]
b = a.reshape(3,6)
print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17]
print(b)
#[[ 0  1  2  3  4  5]
# [ 6  7  8  9 10 11]
# [12 13 14 15 16 17]]
a = np.arange(18)
b = a
print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17]
print(b)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17]
print("resize changes the actual base array")
a.resize(3,6)
print(a)
#[[ 0  1  2  3  4  5]
# [ 6  7  8  9 10 11]
# [12 13 14 15 16 17]]
print(b)
#[[ 0  1  2  3  4  5]
# [ 6  7  8  9 10 11]
# [12 13 14 15 16 17]]

相关内容

最新更新