auser
auser

Reputation: 43

Does numpy treat 1-D slices of arrays in a strange way?

import numpy as np
a = np.array([[(1, 2, 3), 40, 50], [(4, 5, 6), 70, 80]])

Using only numpy operations (i.e., without explicit python-style list construction or loops; the goal is to save time, if possible), how do I create a 2-by-3 numpy array (matrix) [[1,2,3], [4,5,6]] from the above array a?

The slice a[:, 0] produces a 1-D array of shape (2,) that prints as [(1,2,3) (4,5,6)], which obviously cannot be “reshape”d to shape (2, 3). I thought doing np.ravel on a[:, 0] followed by reshaping to (2,3) might solve this problem for me, but unfortunately np.ravel on a[:, 0] yields no change because a[:, 0] is already 1-D.

Is it a known aberration / bug in numpy that numpy doesn’t treat the parentheses of the tuples (1, 2, 3) and (4, 5, 6) in a slice such as a[:, 0] as indicative of rows? Because, as we know, np.array([(1, 2, 3), (4, 5, 6)]) produces a 2-D array of shape (2,3).

Upvotes: 0

Views: 105

Answers (2)

Paul Panzer
Paul Panzer

Reputation: 53099

If all rows have the same structure you can get behavior close to what you want:

a = np.array([((1, 2, 3), 40, 50), ((4, 5, 6), 70, 80)], dtype=("(3,)i,i,i"))

Note that you have to set up a compound dtype indicating the row structure, and that you have to use tuples for the rows in the initializer. The resultant array looks like

a
# array([([1, 2, 3], 40, 50), ([4, 5, 6], 70, 80)],
#       dtype=[('f0', '<i4', (3,)), ('f1', '<i4'), ('f2', '<i4')])

You can access the bit of interest by field name

a['f0']
# array([[1, 2, 3],
#        [4, 5, 6]], dtype=int32)

a['f0'].shape
# (2, 3)

Upvotes: 0

hpaulj
hpaulj

Reputation: 231665

In [30]: a = np.array([[(1, 2, 3), 40, 50], [(4, 5, 6), 70, 80]])               

Look at a:

In [31]: a                                                                      
Out[31]: 
array([[(1, 2, 3), 40, 50],
       [(4, 5, 6), 70, 80]], dtype=object)
In [32]: a.shape                                                                
Out[32]: (2, 3)

1st column - 2 items, both tuples

In [33]: a[:,0]                                                                 
Out[33]: array([(1, 2, 3), (4, 5, 6)], dtype=object)

they can be joined into one 2d array with:

In [34]: np.stack(_)                                                            
Out[34]: 
array([[1, 2, 3],
       [4, 5, 6]])

The structure of these last two arrays is quite different. One has 2 elements, references to tuples else where in memory. The other has 6 elements, numbers, not references, with 2d shape and strides.

This is different:

In [35]: np.array([(1, 2, 3), (4, 5, 6)])                                       
Out[35]: 
array([[1, 2, 3],
       [4, 5, 6]])

It constructs an array from a list of tuples. Out[33] constructs an array from an existing array (with object dtype).

Upvotes: 1

Related Questions