12

I'm trying to find a neat little trick for slicing a row/column from a 2d array and obtaining an array of (col_size x 1) or (1 x row_size).

Is there an easier way than to use numpy.reshape() after every slicing?

Cheers, Stephan

3
  • Can you provide an example of expected input and output please? Do you want to obtain a 1D array or 2D array? Commented Sep 24, 2015 at 14:40
  • Sure! Let's say I have an array like np.ones((2,40)). From this array I want to slice a whole row in the form of an np.array((1,40)). The result should be a 2d array Commented Sep 24, 2015 at 14:43
  • 1
    Use np.newaxis or None to insert a new axis Commented Sep 24, 2015 at 14:45

3 Answers 3

17

You can slice and insert a new axis in one single operation. For example, here's a 2D array:

>>> a = np.arange(1, 7).reshape(2, 3)
>>> a
array([[1, 2, 3],
       [4, 5, 6]])

To slice out a single column (returning array of shape (2, 1)), slice with None as the third dimension:

>>> a[:, 1, None]
array([[2],
       [5]])

To slice out a single row (returning array of shape (1, 3)), slice with None as the second dimension:

>>> a[0, None, :]
array([[1, 2, 3]])
Sign up to request clarification or add additional context in comments.

2 Comments

No problem! Indexing/reshaping takes a while to wrap your head around (at least it did for me), but makes sense after a bit of practice. The docs are pretty good for explaining what's happening here (the basic slicing section).
Curiously I never thought to combine the indexing with the None addition. I guess it is just the force of habit, using None to expand the dimensions of an existing array. And it is faster.
7

Make the index a slice, list or array

    X[[0],:]
    X[0:1,4]

But there's nothing wrong with reshape other than the fact that it requires typing. It isn't slow. [None,:] is a nice short hand for it.

Use of a list index may be the shortest, but it does produce a copy (a plus or minus?) and is slower

For (100,100) integer array:

In [487]: timeit x[[50],:]
100000 loops, best of 3: 10.3 µs per loop  # slowest

In [488]: timeit x[50:51,:]
100000 loops, best of 3: 2.24 µs per loop   # slice indexing is fast

In [489]: timeit x[50,:].reshape(1,-1)
100000 loops, best of 3: 3.29 µs per loop  # minimal time penalty

In [490]: timeit x[50,:][None,:]
100000 loops, best of 3: 3.55 µs per loop

In [543]: timeit x[None,50,:]          # **best**
1000000 loops, best of 3: 1.76 µs per loop

One test for copy is to compare the data buffer pointer with the original.

In [492]: x.__array_interface__['data']
Out[492]: (175920456, False)
In [493]: x[50,:].__array_interface__['data']
Out[493]: (175940456, False)
In [494]: x[[50],:].__array_interface__['data']
Out[494]: (175871672, False)    # different pointer
In [495]: x[50:51,:].__array_interface__['data']
Out[495]: (175940456, False)
In [496]: x[50,:][None,:].__array_interface__['data']
Out[496]: (175940456, False)

2 Comments

The problem is that I'm implementing a scalable neural network, scalable in terms of layer sizes. With reshape I had to access very often different instance attributes (e.g. the layer sizes). Finally to get it right: when I use a[0, None, :] to slice a row from array a, will it then return a copy?
[0, None, :] returns a view.
5

How about this nice and easy way?

In [73]: arr = (np.arange(5, 25)).reshape(5, 4)

In [74]: arr
Out[74]: 
array([[ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16],
       [17, 18, 19, 20],
       [21, 22, 23, 24]])

# extract column 1 as a column vector
In [79]: col1 = arr[:, [0]]
In [80]: col1.shape
Out[80]: (5, 1)

In [81]: col1
Out[81]: 
array([[ 5],
       [ 9],
       [13],
       [17],
       [21]])


# extract row 1 as a row vector
In [82]: row1 = arr[[0], :]

In [83]: row1.shape
Out[83]: (1, 4)

In [84]: row1
Out[84]: array([[5, 6, 7, 8]])

3 Comments

Thank you for the clean and detailed answer! But haven't you noticed that the question is more than two years old? Cheers :)
@neurotronix I just realized that. Anyway, for pedagogical reasons, time never matters ;)
Very true, thanks for taking the time to put up an answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.