NumPy is a library for Python which lets you work with huge, multidimensional matrices and arrays. Along with that, it provides a gamut of high-level functions to perform mathematical operations on these structures.

Documentation: https://numpy.org/doc/stable/reference/index.html

Python has lists that serve the purpose of arrays, but they are slow to process.

NumPy aims to provide an array object that is up to 50x faster that traditional Python lists.

The array object in NumPy is called **ndarray** (n-dimensional array), it provides a lot of supporting functions that make working with ndarray very easy.

Arrays are very frequently used in data science, where speed and resources are very important.

This is one of the most important features of numpy. ndarray is an n-dimensional array, a grid of values of the same kind. A tuple of nonnegative integers indexes this tuple. An array’s rank is its number of dimensions.

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

Output:

```
<class 'numpy.ndarray'>
```

```
print (a.shape)
```

Output:

```
(3,)
```

```
print (a)
```

Output:

```
[1 2 3]
```

```
a[2] = 5
print (a)
```

Output:

```
[1 2 5]
```

Array's shape is (3,). How to create multidimensional array:

```
b = np.array([[2,7,9],[5,1,3]])
print (b)
```

Output:

```
[[2 7 9]
[5 1 3]]
```

```
print (b.shape)
```

Output:

```
(2, 3)
```

```
b[1, 2] = 10
print (b)
print (b.ndim) # Number of dimensions
```

Output:

```
[[ 2 7 9]
[ 5 1 10]]
2
```

```
c = np.arange(7) # This is like range in Python
print (c)
```

Output:

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

```
d = np.random.random((2,2)) # Fills in random values between 0 and 1
print (d)
```

Output:

```
[[0.01207278 0.86017372]
[0.63199496 0.92510335]]
```

```
e = np.full((2,3), 9)
print (e)
```

Output:

```
[[9 9 9]
[9 9 9]]
```

```
f = np.linspace(10,20,6) #6 values spaced evenly between, and including, 10 and 20.
print (f)
```

Output:

```
[10. 12. 14. 16. 18. 20.]
```

A NumPy array holds elements of the same kind. If while creating a NumPy array, you do not specify the data type, NumPy will decide it automatically. NumPy has following data types:

```
bool_
int_
intc
intp
int8
int16
int32
int64
uint8
uint16
uint32
uint64
float_
float16
float32
float64
complex_
complex64
complex128
```

Slicing in python means taking elements from one given index to another given index.

We pass slice instead of index like this: `[start:end]`

.

We can also define the step, like this: `[start:end:step]`

.

If we don't pass start its considered 0

If we don't pass end its considered length of array in that dimension

If we don't pass step its considered 1

```
arr = np.array([1, 2, 3, 4, 5, 6, 7])
arr2 = arr[2:4]
print (arr)
print (arr2)
```

Output:

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

Changes to a sliced array also modify the original:

```
arr2[0] = 10
print (arr)
print (arr2)
```

Output:

```
[ 1 2 10 4 5 6 7]
[10 4]
```