## What will we cover in this Tutorial

If you are starting from scratch with NumPy and do not know what **ndarray** is, then you should read this tutorial first.

- How to make arithmetics with
**ndarray**. - Sliding and indexing of
**ndarray**with 1-dimension. - Sliding and indexing of
**ndarray**with 2-dimensions.

## Arithmetics with NumPy

An amazing feature with **ndarray**s is that you do not need to make **for**–*loops* for simple operations.

```
import numpy as np
a1 = np.array([[1., 2., 3.], [3., 2., 1.]])
a2 = np.array([[4., 5., 6.], [6., 5., 4.]])
print(a1)
print(a2)
print(a2 - a1)
print(a1*a2)
print(1/a1)
print(a2**0.5)
```

This looks too good to be true. *Right?*

The output is as you would expect.

```
[[1. 2. 3.]
[3. 2. 1.]]
[[4. 5. 6.]
[6. 5. 4.]]
[[3. 3. 3.]
[3. 3. 3.]]
[[ 4. 10. 18.]
[18. 10. 4.]]
[[1. 0.5 0.33333333]
[0.33333333 0.5 1. ]]
[[2. 2.23606798 2.44948974]
[2.44948974 2.23606798 2. ]]
```

Then you understand why all are so madly in love with NumPy.

This type of “batch” operation is called *vectorization*.

You can also make comparisons.

```
import numpy as np
a1 = np.array([[1., 2., 3.], [6., 5., 4.]])
a2 = np.array([[4., 5., 6.], [3., 4., 5.]])
print(a1 < a2)
```

Which gives what you expect.

```
[[ True True True]
[False False True]]
```

At least I hope you would expect the above.

## Slicing and basic indexing

If you are familiar with Python lists, then this should not surprise you.

```
import numpy as np
a = np.arange(10)
print(a)
print(a[5])
print(a[2:5])
```

You guessed it.

```
[0 1 2 3 4 5 6 7 8 9]
5
[2 3 4]
```

But this might surprise you a bit.

```
import numpy as np
a = np.arange(10)
print(a)
a[4:7] = 10
print(a)
```

Resulting in.

```
[0 1 2 3 4 5 6 7 8 9]
[ 0 1 2 3 10 10 10 7 8 9]
```

That is quite a surprise.

You can take a “view” from it (also called a slice) like the following example shows.

```
import numpy as np
a = np.arange(10)
print(a)
a_slice = a[4:7]
print(a_slice)
a_slice[0:1] = 30
print(a_slice)
print(a)
```

Resulting in.

```
[0 1 2 3 4 5 6 7 8 9]
[4 5 6]
[30 5 6]
[ 0 1 2 3 30 5 6 7 8 9]
```

## Slicing and indexing of 2-dimensions

First of, this seems similar to Python lists.

```
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a[1])
print(a[2][2])
print(a[2, 2])
```

Maybe the last statement is surprising, but it does the same as the above. That is, the effect of **a[2][2]** is the same as of **a[2, 2]**.

```
[4 5 6]
9
9
```

Slicing the above **ndarray** will be done by rows.

```
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a[:2])
```

Which results in the following.

```
[[1 2 3]
[4 5 6]]
```

A bit more advanced to slice it as.

```
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a[:2, 1:])
```

Resulting in.

```
[[2 3]
[5 6]]
```

It might not be clear the the second slice does fully vertical slices, which is illustrated by the following example.

```
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a[:, :1])
```

This will most likely surprise you. *Right?*

```
[[1]
[4]
[7]]
```

Makes sense, right?