# NumPy: manipulating numerical data¶

*NumPy* is the key Python package for creating and manipulating (multi-dimensional) numerical arrays. *NumPy* arrays are also the most important data objects in \(\omega radlib\). It has become a convention to import *NumPy* as follows:

```
[1]:
```

```
import numpy as np
```

## Creating and inspecting NumPy arrays¶

The `ndarray`

, a numerical array, is the most important data type in NumPy.

```
[2]:
```

```
a = np.array([0, 1, 2, 3])
print(a)
print(type(a))
```

```
[0 1 2 3]
<class 'numpy.ndarray'>
```

Inspect the `shape`

(i.e. the number and size of the dimensions of an array).

```
[3]:
```

```
print(a.shape)
# This creates a 2-dimensional array
a2 = np.array([[0, 1], [2, 3]])
print(a2.shape)
```

```
(4,)
(2, 2)
```

There are various ways to create arrays: from lists (as above), using convenience functions, or from file.

```
[4]:
```

```
# From lists
a = np.array([0, 1, 2, 3])
print("a looks like:\n%r\n" % a)
# Convenience functions
b = np.ones(shape=(2, 3))
print("b looks like:\n%r\nand has shape %r\n" % (b, b.shape))
c = np.zeros(shape=(2, 1))
print("c looks like:\n%r\nand has shape %r\n" % (c, c.shape))
d = np.arange(2, 10)
print("d looks like:\n%r\nand has shape %r\n" % (d, d.shape))
e = np.linspace(0, 10, 5)
print("e looks like:\n%r\nand has shape %r\n" % (e, e.shape))
```

```
a looks like:
array([0, 1, 2, 3])
b looks like:
array([[1., 1., 1.],
[1., 1., 1.]])
and has shape (2, 3)
c looks like:
array([[0.],
[0.]])
and has shape (2, 1)
d looks like:
array([2, 3, 4, 5, 6, 7, 8, 9])
and has shape (8,)
e looks like:
array([ 0. , 2.5, 5. , 7.5, 10. ])
and has shape (5,)
```

You can change the shape of an array without changing its size.

```
[5]:
```

```
a = np.arange(10)
b = np.reshape(a, (2, 5))
print("Array a has shape %r.\nArray b has shape %r" % (a.shape, b.shape))
```

```
Array a has shape (10,).
Array b has shape (2, 5)
```

## Indexing and slicing¶

You can index an `ndarray`

in the same way as a `list`

:

```
[6]:
```

```
a = np.arange(10)
print(a)
print(a[0], a[2], a[-1])
```

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

Just follow your intuition for indexing multi-dimensional arrays:

```
[7]:
```

```
a = np.diag(np.arange(3))
print(a, end="\n\n")
print("Second row, second column: %r\n" % a[1, 1])
# Setting an array item
a[2, 1] = 10 # third line, second column
print(a, end="\n\n")
# Acessing a full row
print("Second row:\n%r" % a[1])
```

```
[[0 0 0]
[0 1 0]
[0 0 2]]
Second row, second column: 1
[[ 0 0 0]
[ 0 1 0]
[ 0 10 2]]
Second row:
array([0, 1, 0])
```

Slicing is just a way to access multiple array items at once:

```
[8]:
```

```
a = np.arange(10)
print(a, end="\n\n")
print("1st:", a[2:9])
print("2nd:", a[2:])
print("3rd:", a[:5])
print("4th:", a[2:9:3]) # [start:end:step]
print("5th:", a[a > 5]) # using a mask
```

```
[0 1 2 3 4 5 6 7 8 9]
1st: [2 3 4 5 6 7 8]
2nd: [2 3 4 5 6 7 8 9]
3rd: [0 1 2 3 4]
4th: [2 5 8]
5th: [6 7 8 9]
```

Get further info on NumPy arrays here!