I have below code that allows me to iterate over a flattened list and maps the updates back to the structured array -
a = np.asarray([1,2,3])
b = np.asarray([4,5,6])
c = np.asarray([a, b])
print c
r = c.ravel()
print r
r[1] = 10
print c
setting r[1] = 10 modifies c[0][1] to 10. I want to do something similar with the lower snippet but this fails and I am assuming it's because the dimensions are inconsistent. Is there some way to get similar behavior so I can modify a flattened version without having to reshape it back to c?
a = np.asarray([1,2,3])
b = np.asarray([4,5,6,7,8])
c = np.asarray([a, b])
r = c.ravel()
r[1] = 10
print r
In your first case c
is a 2d array
In [391]: a = np.asarray([1,2,3])
...: b = np.asarray([4,5,6])
...: c = np.asarray([a, b])
...:
In [392]: c
Out[392]:
array([[1, 2, 3],
[4, 5, 6]])
In [393]: c.shape
Out[393]: (2, 3)
ravel
produces a view of c
, so changes to one appear in the other
In [394]: r = c.ravel()
In [395]: r[1] = 10
In [396]: c
Out[396]:
array([[ 1, 10, 3],
[ 4, 5, 6]])
You can also index c
with flat
, with the same effect:
In [397]: c.flat[4] = 10
In [398]: c
Out[398]:
array([[ 1, 10, 3],
[ 4, 10, 6]])
In [399]: r
Out[399]: array([ 1, 10, 3, 4, 10, 6])
These changes to c
or r
do not affect the original a
or b
. asarray
copies those arrays.
In the second case c
is a 1d array containing other arrays:
In [400]: a = np.asarray([1,2,3])
...: b = np.asarray([4,5,6,7,8])
...: c = np.asarray([a, b])
...:
In [401]: c
Out[401]: array([array([1, 2, 3]), array([4, 5, 6, 7, 8])], dtype=object)
The pieces can be joined into a 1d array:
In [402]: np.concatenate(c)
Out[402]: array([1, 2, 3, 4, 5, 6, 7, 8])
Values can be changed, but won't affect the original c
.
In [403]: c[0][0] = 10
In [404]: c
Out[404]: array([array([10, 2, 3]), array([4, 5, 6, 7, 8])], dtype=object)
This changes the original a
because c
literally contains a
, not a copy of it:
In [405]: a
Out[405]: array([10, 2, 3]
np.array
(or asarray
) tries to make as-a-dimensional array as it can from the inputs. In the first case inputs are equal in size, so it makes a 2d. In the second they differ so it makes a 1d array of objects. This behavior often gives users problems. Either they expect a 2d array in the second case, or they can't produce the object array in the first.
To reliably make an object array, regardless of whether the inputs match in size or not, you have to do something like
In [417]: g = np.empty(2, dtype=object)
In [418]: g[:] = [a, b[:3]]
In [419]: g
Out[419]: array([array([10, 2, 3]), array([4, 5, 6])], dtype=object)