# newaxis¶

The final basic multidimensional index type is `newaxis`

. `np.newaxis`

is an
alias for `None`

. Both `np.newaxis`

and `None`

function identically; however,
`np.newaxis`

is often more explicit than `None`

, which may appear odd in an
index, so it is generally preferred. However, some people do use `None`

directly instead of `np.newaxis`

, so it’s important to remember that they are
the same thing.

```
>>> import numpy as np
>>> print(np.newaxis)
None
>>> np.newaxis is None # They are exactly the same thing
True
```

`newaxis`

, as the name suggests, adds a new axis to an array. This new axis
has size `1`

. The new axis is added at the corresponding location within the
array shape. A size `1`

axis neither adds nor removes any elements from the
array. Using the nested lists analogy, it essentially
adds a new “layer” to the list of lists.

```
>>> b = np.arange(4)
>>> b
array([0, 1, 2, 3])
>>> b[np.newaxis]
array([[0, 1, 2, 3]])
>>> b.shape
(4,)
>>> b[np.newaxis].shape
(1, 4)
```

Including `newaxis`

alongside other indices in a tuple index does
not affect which axes those indices select. You can think of the `newaxis`

index as inserting the new axis in-place in the index, so that the other
indices still select the same corresponding axes they would select if it
weren’t there.

Take our example array, which has shape `(3, 2, 4)`

:

```
>>> a = np.arange(24).reshape((3, 2, 4))
>>> a.shape
(3, 2, 4)
```

The index `a[0, :2]`

results in a shape of `(2, 4)`

: the integer index `0`

removes the first axis, the slice `:2`

selects 2 elements from the second
axis, and the third axis is not selected at all, so it remains intact with 4
elements.

```
>>> a[0, :2]
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
>>> a[0, :2].shape
(2, 4)
```

Now, observe the shape of `a`

when we insert `newaxis`

at various points
within the index `a[0, :2]`

:

```
>>> a[np.newaxis, 0, :2].shape
(1, 2, 4)
>>> a[0, np.newaxis, :2].shape
(1, 2, 4)
>>> a[0, :2, np.newaxis].shape
(2, 1, 4)
>>> a[0, :2, ..., np.newaxis].shape
(2, 4, 1)
```

In each case, the exact same elements are selected: `0`

always targets the
first axis, and `:2`

always targets the second axis. The only difference is
where the size `1`

axis is inserted:

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

Let’s look at each of these more closely:

`a[np.newaxis, 0, :2]`

: the new axis is inserted before the first axis, but the`0`

and`:2`

still index the original first and second axes. The resulting shape is`(1, 2, 4)`

.`a[0, np.newaxis, :2]`

: the new axis is inserted after the first axis, but because the`0`

removes this axis when it indexes it, the resulting shape is still`(1, 2, 4)`

(and the resulting array is the same).`a[0, :2, np.newaxis]`

: the new axis is inserted after the second axis, because the`newaxis`

comes right after the`:2`

, which indexes the second axis. The resulting shape is`(2, 1, 4)`

. Remember that the`4`

in the shape corresponds to the last axis, which isn’t represented in the index at all. That’s why in this example, the`4`

still comes at the end of the resulting shape.`a[0, :2, ..., np.newaxis]`

: the`newaxis`

is after an ellipsis, so the new axis is inserted at the end of the shape. The resulting shape is`(2, 4, 1)`

.

In general, in a tuple index, the axis that each index selects corresponds to
its position in the tuple index after removing any `newaxis`

indices.
Equivalently, `newaxis`

indices can be though of as adding new axes *after*
the existing axes are indexed.

A size `1`

axis can always be inserted anywhere in an array’s shape without
changing the underlying elements.

An array index can include multiple instances of `newaxis`

(or `None`

). Each
will add a size `1`

axis in the corresponding location.

**Exercise:** Can you determine the shape of this array, given that `a.shape`

is `(3, 2, 4)`

?

```
a[np.newaxis, 0, newaxis, :2, newaxis, ..., newaxis]
```

## Click here to show the solution

```
>>> a[np.newaxis, 0, np.newaxis, :2, np.newaxis, ..., np.newaxis].shape
(1, 1, 2, 1, 4, 1)
```

In summary,

`np.newaxis`

(which is just an alias for`None`

) inserts a new size`1`

axis in the corresponding location in the tuple index. The remaining, non-`newaxis`

indices in the tuple index are indexed as if the`newaxis`

indices were not there.

## Where `newaxis`

is Used¶

What we haven’t said yet is why you would want to do such a thing in the first place. One use case is to explicitly convert a 1-D vector into a 2-D matrix representing a row or column vector. For example,

```
>>> v = np.array([0, 1, -1])
>>> v.shape
(3,)
>>> v[np.newaxis]
array([[ 0, 1, -1]])
>>> v[np.newaxis].shape
(1, 3)
>>> v[..., np.newaxis]
array([[ 0],
[ 1],
[-1]])
>>> v[..., np.newaxis].shape
(3, 1)
```

`v[newaxis]`

inserts an axis at the beginning of the shape, making `v`

a `(1, 3)`

row vector and `v[..., newaxis]`

inserts an axis at the end, making it a
`(3, 1)`

column vector.

But the most common usage is due to broadcasting. The key idea
of broadcasting is that size `1`

dimensions are not directly useful, in the
sense that they could be removed without actually changing anything about the
underlying data in the array. So they are used as a signal that that dimension
can be repeated in operations. `newaxis`

is therefore useful for inserting
these size `1`

dimensions in situations where you want to force your data to
be repeated. For example, suppose we have the two arrays

```
>>> x = np.array([1, 2, 3])
>>> y = np.array([100, 200])
```

and suppose we want to compute an “outer” sum of `x`

and `y`

, that is, we want
to compute every combination of `a + b`

where `a`

is from `x`

and `b`

is from
`y`

. The key realization here is that what we want is simply to
repeat each entry of `x`

2 times, to correspond to each entry of `y`

, and
respectively repeat each entry of `y`

3 times, to correspond to each entry of
`x`

. And this is exactly the sort of thing broadcasting does! We only need to
make the shapes of `x`

and `y`

match in such a way that the broadcasting will
do that. Since we want both `x`

and `y`

to be repeated, we will need to
broadcast both arrays. We want to compute

```
[[ x[0] + y[0], x[0] + y[1] ],
[ x[1] + y[0], x[1] + y[1] ],
[ x[2] + y[0], x[2] + y[1] ]]
```

That way the first dimension of the resulting array will correspond to values
from `x`

, and the second dimension will correspond to values from `y`

, i.e.,
`a[i, j]`

will be `x[i] + y[j]`

. Thus the resulting array will have shape `(3, 2)`

. So to make `x`

(which is shape `(3,)`

) and `y`

(which is shape `(2,)`

)
broadcast to this, we need to make them `(3, 1)`

and `(1, 2)`

, respectively.
This can easily be done with `np.newaxis`

:

```
>>> x[:, np.newaxis].shape
(3, 1)
>>> y[np.newaxis, :].shape
(1, 2)
```

Once we have the desired shapes, we just perform the operation, and NumPy will do the broadcasting automatically.[1]

```
>>> x[:, np.newaxis] + y[np.newaxis, :]
array([[101, 201],
[102, 202],
[103, 203]])
```

Note: broadcasting automatically prepends size `1`

dimensions, so the
`y[np.newaxis, :]`

operation is unnecessary.

```
>>> x[:, np.newaxis] + y
array([[101, 201],
[102, 202],
[103, 203]])
```

As we saw before, size `1`

dimensions may seem redundant,
but they are not a bad thing. Not only do they allow indexing an array
uniformly, they are also very important in the way they interact with NumPy’s
broadcasting rules.

Footnotes