How does numpy.newaxis work and when to use it?

319,255

Solution 1

Simply put, numpy.newaxis is used to increase the dimension of the existing array by one more dimension, when used once. Thus,

  • 1D array will become 2D array

  • 2D array will become 3D array

  • 3D array will become 4D array

  • 4D array will become 5D array

and so on..

Here is a visual illustration which depicts promotion of 1D array to 2D arrays.

newaxis canva visualization


Scenario-1: np.newaxis might come in handy when you want to explicitly convert a 1D array to either a row vector or a column vector, as depicted in the above picture.

Example:

# 1D array
In [7]: arr = np.arange(4)
In [8]: arr.shape
Out[8]: (4,)

# make it as row vector by inserting an axis along first dimension
In [9]: row_vec = arr[np.newaxis, :]     # arr[None, :]
In [10]: row_vec.shape
Out[10]: (1, 4)

# make it as column vector by inserting an axis along second dimension
In [11]: col_vec = arr[:, np.newaxis]     # arr[:, None]
In [12]: col_vec.shape
Out[12]: (4, 1)

Scenario-2: When we want to make use of numpy broadcasting as part of some operation, for instance while doing addition of some arrays.

Example:

Let's say you want to add the following two arrays:

 x1 = np.array([1, 2, 3, 4, 5])
 x2 = np.array([5, 4, 3])

If you try to add these just like that, NumPy will raise the following ValueError :

ValueError: operands could not be broadcast together with shapes (5,) (3,)

In this situation, you can use np.newaxis to increase the dimension of one of the arrays so that NumPy can broadcast.

In [2]: x1_new = x1[:, np.newaxis]    # x1[:, None]
# now, the shape of x1_new is (5, 1)
# array([[1],
#        [2],
#        [3],
#        [4],
#        [5]])

Now, add:

In [3]: x1_new + x2
Out[3]:
array([[ 6,  5,  4],
       [ 7,  6,  5],
       [ 8,  7,  6],
       [ 9,  8,  7],
       [10,  9,  8]])

Alternatively, you can also add new axis to the array x2:

In [6]: x2_new = x2[:, np.newaxis]    # x2[:, None]
In [7]: x2_new     # shape is (3, 1)
Out[7]: 
array([[5],
       [4],
       [3]])

Now, add:

In [8]: x1 + x2_new
Out[8]: 
array([[ 6,  7,  8,  9, 10],
       [ 5,  6,  7,  8,  9],
       [ 4,  5,  6,  7,  8]])

Note: Observe that we get the same result in both cases (but one being the transpose of the other).


Scenario-3: This is similar to scenario-1. But, you can use np.newaxis more than once to promote the array to higher dimensions. Such an operation is sometimes needed for higher order arrays (i.e. Tensors).

Example:

In [124]: arr = np.arange(5*5).reshape(5,5)

In [125]: arr.shape
Out[125]: (5, 5)

# promoting 2D array to a 5D array
In [126]: arr_5D = arr[np.newaxis, ..., np.newaxis, np.newaxis]    # arr[None, ..., None, None]

In [127]: arr_5D.shape
Out[127]: (1, 5, 5, 1, 1)

As an alternative, you can use numpy.expand_dims that has an intuitive axis kwarg.

# adding new axes at 1st, 4th, and last dimension of the resulting array
In [131]: newaxes = (0, 3, -1)
In [132]: arr_5D = np.expand_dims(arr, axis=newaxes)
In [133]: arr_5D.shape
Out[133]: (1, 5, 5, 1, 1)

More background on np.newaxis vs np.reshape

newaxis is also called as a pseudo-index that allows the temporary addition of an axis into a multiarray.

np.newaxis uses the slicing operator to recreate the array while numpy.reshape reshapes the array to the desired layout (assuming that the dimensions match; And this is must for a reshape to happen).

Example

In [13]: A = np.ones((3,4,5,6))
In [14]: B = np.ones((4,6))
In [15]: (A + B[:, np.newaxis, :]).shape     # B[:, None, :]
Out[15]: (3, 4, 5, 6)

In the above example, we inserted a temporary axis between the first and second axes of B (to use broadcasting). A missing axis is filled-in here using np.newaxis to make the broadcasting operation work.


General Tip: You can also use None in place of np.newaxis; These are in fact the same objects.

In [13]: np.newaxis is None
Out[13]: True

P.S. Also see this great answer: newaxis vs reshape to add dimensions

Solution 2

What is np.newaxis?

The np.newaxis is just an alias for the Python constant None, which means that wherever you use np.newaxis you could also use None:

>>> np.newaxis is None
True

It's just more descriptive if you read code that uses np.newaxis instead of None.

How to use np.newaxis?

The np.newaxis is generally used with slicing. It indicates that you want to add an additional dimension to the array. The position of the np.newaxis represents where I want to add dimensions.

>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.shape
(10,)

In the first example I use all elements from the first dimension and add a second dimension:

>>> a[:, np.newaxis]
array([[0],
       [1],
       [2],
       [3],
       [4],
       [5],
       [6],
       [7],
       [8],
       [9]])
>>> a[:, np.newaxis].shape
(10, 1)

The second example adds a dimension as first dimension and then uses all elements from the first dimension of the original array as elements in the second dimension of the result array:

>>> a[np.newaxis, :]  # The output has 2 [] pairs!
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> a[np.newaxis, :].shape
(1, 10)

Similarly you can use multiple np.newaxis to add multiple dimensions:

>>> a[np.newaxis, :, np.newaxis]  # note the 3 [] pairs in the output
array([[[0],
        [1],
        [2],
        [3],
        [4],
        [5],
        [6],
        [7],
        [8],
        [9]]])
>>> a[np.newaxis, :, np.newaxis].shape
(1, 10, 1)

Are there alternatives to np.newaxis?

There is another very similar functionality in NumPy: np.expand_dims, which can also be used to insert one dimension:

>>> np.expand_dims(a, 1)  # like a[:, np.newaxis]
>>> np.expand_dims(a, 0)  # like a[np.newaxis, :]

But given that it just inserts 1s in the shape you could also reshape the array to add these dimensions:

>>> a.reshape(a.shape + (1,))  # like a[:, np.newaxis]
>>> a.reshape((1,) + a.shape)  # like a[np.newaxis, :]

Most of the times np.newaxis is the easiest way to add dimensions, but it's good to know the alternatives.

When to use np.newaxis?

In several contexts is adding dimensions useful:

  • If the data should have a specified number of dimensions. For example if you want to use matplotlib.pyplot.imshow to display a 1D array.

  • If you want NumPy to broadcast arrays. By adding a dimension you could for example get the difference between all elements of one array: a - a[:, np.newaxis]. This works because NumPy operations broadcast starting with the last dimension 1.

  • To add a necessary dimension so that NumPy can broadcast arrays. This works because each length-1 dimension is simply broadcast to the length of the corresponding1 dimension of the other array.


1 If you want to read more about the broadcasting rules the NumPy documentation on that subject is very good. It also includes an example with np.newaxis:

>>> a = np.array([0.0, 10.0, 20.0, 30.0])
>>> b = np.array([1.0, 2.0, 3.0])
>>> a[:, np.newaxis] + b
array([[  1.,   2.,   3.],
       [ 11.,  12.,  13.],
       [ 21.,  22.,  23.],
       [ 31.,  32.,  33.]])

Solution 3

You started with a one-dimensional list of numbers. Once you used numpy.newaxis, you turned it into a two-dimensional matrix, consisting of four rows of one column each.

You could then use that matrix for matrix multiplication, or involve it in the construction of a larger 4 x n matrix.

Solution 4

newaxis object in the selection tuple serves to expand the dimensions of the resulting selection by one unit-length dimension.

It is not just conversion of row matrix to column matrix.

Consider the example below:

In [1]:x1 = np.arange(1,10).reshape(3,3)
       print(x1)
Out[1]: array([[1, 2, 3],
               [4, 5, 6],
               [7, 8, 9]])

Now lets add new dimension to our data,

In [2]:x1_new = x1[:,np.newaxis]
       print(x1_new)
Out[2]:array([[[1, 2, 3]],

              [[4, 5, 6]],

              [[7, 8, 9]]])

You can see that newaxis added the extra dimension here, x1 had dimension (3,3) and X1_new has dimension (3,1,3).

How our new dimension enables us to different operations:

In [3]:x2 = np.arange(11,20).reshape(3,3)
       print(x2)
Out[3]:array([[11, 12, 13],
              [14, 15, 16],
              [17, 18, 19]]) 

Adding x1_new and x2, we get:

In [4]:x1_new+x2
Out[4]:array([[[12, 14, 16],
               [15, 17, 19],
               [18, 20, 22]],

              [[15, 17, 19],
               [18, 20, 22],
               [21, 23, 25]],

              [[18, 20, 22],
               [21, 23, 25],
               [24, 26, 28]]])

Thus, newaxis is not just conversion of row to column matrix. It increases the dimension of matrix, thus enabling us to do more operations on it.

Share:
319,255

Related videos on Youtube

Yue Harriet Huang
Author by

Yue Harriet Huang

Updated on July 08, 2022

Comments

  • Yue Harriet Huang
    Yue Harriet Huang almost 2 years

    When I try

    numpy.newaxis
    

    the result gives me a 2-d plot frame with x-axis from 0 to 1. However, when I try using numpy.newaxis to slice a vector,

    vector[0:4,]
    [ 0.04965172  0.04979645  0.04994022  0.05008303]
    vector[:, np.newaxis][0:4,]
    [[ 0.04965172]
    [ 0.04979645]
    [ 0.04994022]
    [ 0.05008303]]
    

    Is it the same thing except that it changes a row vector to a column vector?

    Generally, what is the use of numpy.newaxis, and in which circumstances should we use it?

    • endolith
      endolith almost 6 years
      except that it changes a row vector to a column vector? The first example is not a row vector. That's a matlab concept. In python it's just a 1-dimensional vector with no row or column concept. Row or column vectors are 2-dimensonal, like the second example
    • rocksNwaves
      rocksNwaves almost 3 years
      That term does not come from matlab, it is a mathematical concept and a perfectly valid way to describe the arrays in his example. math.stackexchange.com/questions/1198729/…
  • Stephen
    Stephen almost 7 years
    What type of operation is x1_new + x2? It is weird to me because I thought that two matrices can only be added if they have the same dimensions (or if one of them is actually just a scalar).
  • kmario23
    kmario23 almost 7 years
    @Stephen As I also noted in the answer, it's because of NumPy Broadcasting.
  • kmario23
    kmario23 over 6 years
    It's not just matrix, it works with any ndarray in NumPy terminology.
  • Valdrinium
    Valdrinium over 4 years
    This is an awesome explaination
  • kmario23
    kmario23 over 4 years
    @valdrinit glad that it's helpful for you :)
  • Chiraz BenAbdelkader
    Chiraz BenAbdelkader almost 4 years
    Either @kmario23 == Ian Dzindo, or Ian Dzindo01 plagiarized this answer in this 2018 Medium post: medium.com/@ian.dzindo01/….
  • kmario23
    kmario23 almost 4 years
    @ChirazBenAbdelkader I'm not the one who wrote that medium post. Yes, it's ditto copying but there was an attribution at the end of the article, although I'd prefer it to be at the beginning.
  • Chiraz BenAbdelkader
    Chiraz BenAbdelkader almost 4 years
    @kmario23 Indeed the attribution is hidden in the very last sentence of the article, no wonder I did not see it. I consider it borderline plagiarism even with this attribution. In my book, word for word copying is only acceptable if it's the same author posting on different platforms. I expected better from Medium.
  • Chiraz BenAbdelkader
    Chiraz BenAbdelkader almost 4 years
    I don't see the difference between the 2nd and 3rd use cases; they're both about allowing NumPy to broadcast an array as part of some operation. If not, then it would help to add an example for the 3rd use case in order to clarify the point.
  • MSeifert
    MSeifert almost 4 years
    @ChirazBenAbdelkader Yeah, the distinction isn't really that distinct. I'm not sure if I should remove the third point or merge it into the second one.
  • Mike Williamson
    Mike Williamson over 3 years
    Awesome... I wish I could give more than one thumbs up. :)
  • Darkonaut
    Darkonaut over 3 years
    "Wait, it's all None? -Always has been."
  • TheExorcist
    TheExorcist over 2 years
    Modality for explanation is great, if you are MEME type go for pic, wanna see the implementation go to the code. - Beautiful
  • kmario23
    kmario23 over 2 years
    Danke!! What you said is absolutely correct.