# Python NumPy For Your Grandma - 4.5 Stacking

In this section, we’ll see how the functions `hstack()`

, `vstack()`

, and `stack()`

are a lot like the `concatenate()`

function with some subtle differences that can come in handy.

Let’s start by building some helper arrays. We’ll make a (2,) array called `foo`

, another (2,) array called `bar`

, a (1,2) array called `baz`

, a (1,3) array called `bingo`

, and a (2,2) array called `bongo`

.

```
import numpy as np
foo = np.array(['a', 'b'])
bar = np.array(['c', 'd'])
baz = np.array([['e', 'f']])
bingo = np.array([['g', 'h', 'i']])
bongo = np.array(
[['j', 'k'],
['l', 'm']]
)
```

Now let’s take a look at `vstack()`

. `vstack()`

takes one argument - a sequence of arrays, and you could describe its algorithm in pseudocode as the following.

```
for each array in the sequence:
if the array is 1d
then promote the array to 2d by giving it a new front axis
if every array in the sequence has the same shape:
then concatenate the arrays along axis 0
otherwise throw an error
```

Visually, you could imagine `vstack()`

as vertically stacking 1-d or 2-d arrays. So if we `vstack()`

`foo`

and `bar`

,
we’ll get back a 2x2 array like this.

```
np.vstack((foo, bar))
## array([['a', 'b'],
## ['c', 'd']], dtype='<U1')
```

And if we `vstack()`

`foo`

, `bar`

, and `baz`

, we’ll get back a 3x2 array like this.

```
np.vstack((foo, bar, baz))
## array([['a', 'b'],
## ['c', 'd'],
## ['e', 'f']], dtype='<U1')
```

And if `vstack()`

`baz`

and `bingo`

, we’ll get an error because their shapes don’t align for `vstack()`

.

```
np.vstack((baz, bingo)) # error
```

Now let’s take a look at `hstack()`

. `hstack()`

also takes one argument - a sequence of arrays, and you could describe its
algorithm in pseudocode as the following.

```
if every array in the sequence is 1d:
then concatenate the arrays along axis 0
else:
if every array has the same shape excluding axis 1:
then concatenate arrays along axis 1
otherwise throw an error
```

Visually, you could imagine `hstack()`

as horizontally stacking 1-d or 2-d arrays. So if we `hstack()`

`foo`

and `bar`

, we’ll get back a 4x array like this.

```
np.hstack((foo, bar))
## array(['a', 'b', 'c', 'd'], dtype='<U1')
```

If we `hstack()`

`baz`

and `bingo`

, we’ll get back a 5x array like this.

```
np.hstack((baz, bingo))
## array([['e', 'f', 'g', 'h', 'i']], dtype='<U1')
```

If we `hstack()`

`foo`

and `bingo`

, we’ll get back an error because their shapes don’t align for `hstack()`

.

```
np.hstack((foo, bingo)) # error
```

And if we `hstack()`

`bingo`

and `bongo`

, we’ll get another error because their shapes also don’t align for `hstack()`

.

```
np.hstack((bingo, bongo)) # error
```

Lastly, `stack()`

takes two arguments, a sequence of arrays to combine, and `axis`

, which tells stack to create a new axis
along which to combine the arrays. In pseudocode, you could write stack’s algorithm as the following.

```
if every array is the same shape and axis is less than or equal to the dimensionality of the arrays:
then for each array:
insert a new axis where specified
then concatenate the arrays along the new axis
otherwise throw an error
```

So, let’s see what happens if we `stack()`

`foo`

and `bar`

with `axis=0`

. Remember the algorithm. `foo`

and `bar`

each get a new axis 0, promoting them from 2x arrays to 1x2 arrays, and then they’re stacked along that new axis; so, row-wise, resulting in a new 2x2 array.

```
np.stack((foo, bar), axis = 0)
## array([['a', 'b'],
## ['c', 'd']], dtype='<U1')
```

If we `stack()`

them along axis 1, they go from 2x arrays to 2x1 arrays and then get stacked column-wise into a new 2x2 array.

```
np.stack((foo, bar), axis = 1)
## array([['a', 'c'],
## ['b', 'd']], dtype='<U1')
```

If we try to `stack()`

`foo`

and `bar`

with `axis=2`

we’ll get an out of bounds error. Remember, the new axis must be in range of the arrays’ existing dimensionality.

```
np.stack((foo, bar), axis = 2) # error
```

You can also use the `axis = -1`

shortcut to make the new axis the last axis. For `foo`

and `bar`

, it’d be like using `axis = 1`

.

```
np.stack((foo, bar), axis = -1)
## array([['a', 'c'],
## ['b', 'd']], dtype='<U1')
```

## Course Curriculum

**Introduction**

1.1 Introduction**Basic Array Stuff**

2.1 NumPy Array Motivation

2.2 NumPy Array Basics

2.3 Creating NumPy Arrays

2.4 Indexing 1-D Arrays

2.5 Indexing Multidimensional Arrays

2.6 Basic Math On Arrays

2.7 Challenge: High School Reunion

2.8 Challenge: Gold Miner

2.9 Challenge: Chic-fil-A**Intermediate Array Stuff**

3.1 Broadcasting

3.2 newaxis

3.3`reshape()`

3.4 Boolean Indexing

3.5 nan

3.6 infinity

3.7 random

3.8 Challenge: Love Distance

3.9 Challenge: Professor Prick

3.10 Challenge: Psycho Parent**Common Operations**

4.1`where()`

4.2 Math Functions

4.3`all()`

and`any()`

4.4`concatenate()`

4.5 Stacking

4.6 Sorting

4.7`unique()`

4.8 Challenge: Movie Ratings

4.9 Challenge: Big Fish

4.10 Challenge: Taco Truck**Advanced Array Stuff**

5.1 Advanced Array Indexing

5.2 View vs Copy

5.3 Challenge: Population Verification

5.4 Challenge: Prime Locations

5.5 Challenge: The Game of Doors

5.6 Challenge: Peanut Butter**Final Boss**

6.1`as_strided()`

6.2`einsum()`

6.3 Challenge: One-Hot-Encoding

6.4 Challenge: Cumulative Rainfall

6.5 Challenge: Table Tennis

6.6 Challenge: Where’s Waldo

6.7 Challenge: Outer Product