Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
147 views
in Technique[技术] by (71.8m points)

python - What does it mean "The reshape function returns its argument with a modified shape, whereas the ndarray.resize method modifies the array itself"?

In Numpy, the reshape function returns its argument with a modified shape, whereas the ndarray.resize method modifies the array itself. But what does this really mean? What's the real difference?

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]]

From the code above, resize() and reshape() perform the same operation, on the same data. Why need two of them?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
In [15]: a = np.arange(18) 
    ...: b = a.reshape(3,6)  

I like to examine the properties of arrays with:

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}

Note that data is the same for both. b is a view of a. It is a new array object, but it shares the underlying data buffer. Its shape is different, but changes to a will appear as changes in b (and visa versa).

Review documentation regarding view versus copy. This is an important distinction in numpy, so you need to understand it well.

Sometimes reshape has to return a copy, as when order gets changed. It's also important to realize the reshape cannot change the number of elements.

There's a reshape function as well, which in most cases the same as the method.

The shape attribute can be changed directly as well:

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]])

That action is in-place, modifying a itself. It's a little more restrictive than reshape, and not used as often. For example we could have made b with one line:

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

The key difference in resize is that it can change the number of elements. It can truncate, or it can increase the size. The resize method and function both do this, but have different 'padding' rules. And the resize method operates in-place.

In your example, a.resize(3,6) changed a in-place, changing its shape, but did not change its data buffer, or b's link to that buffer. So changes to a also appeared as changes in b.

My a after the in-place shape change still has the same data:

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

and the same data after a resize method.

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}

Note that if I try to resize a in a way that changes the total number of elements, I get an error. That's because b shares the data buffer, and we can't change the size of a without affecting the size of b.

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

I think you'll find np.reshape and a.reshape are used quite a bit. resize in either form is not used nearly as often. reshape is more predictable and safer. resize can do the same, but it also lets you do dangerous stuff.

I'd focus on understanding the difference between a view and copy, and secondarily the difference between making a new array and doing in-place changes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...