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.