This Python Numpy tutorial for beginners talks about Numpy basic concepts, practical examples, and real-world Numpy use cases related to machine learning and data science

## What is NumPy?

**NumPy **in python** **is a general-purpose array-processing package. It stands for **Numerical Python**. NumPy helps to create arrays (multidimensional arrays), with the help of bindings of C++. Therefore, it is quite fast. There are in-built functions of NumPy as well. It is the fundamental package for scientific computing with Python.

The NumPy library also contains a multidimensional array and matrix data structures. It provides **ndarray**, a homogeneous n-dimensional array object, with methods to efficiently operate on it.

It is one of the very important libraries used in the field of Data Science & Machine Learning.

Here is an interesting search trend for NumPy for the last five years.

## Why do we need NumPy?

Does a question arise that **why do we need a NumPy array when we have python lists?**

The answer is we can perform operations on all the elements of a NumPy array at once, which are not possible with python lists.

For example, we can’t multiply two lists directly we will have to do it element-wise. This is where the role of NumPy comes into play.

**Example:**

```
list1 = [2, 4, 6, 7, 8]
list2 = [3, 4, 6, 1, 5]
print(list1*list2)
```

**Output:**

`TypeError: can't multiply sequence by non-int of type 'list'`

Where the same thing can be done easily with NumPy arrays. Here is how NumPy works.

**Numpy Array Example:**

```
import numpy as np
list1 = [2, 4, 6, 7, 8]
list2 = [3, 4, 6, 1, 5]
arr1 = np.array(list1)
arr2 = np.array(list2)
print(arr1*arr2)
```

**Output:**

`[ 6 16 36 7 40]`

## Python Numpy Tutorial

In this section, we will start with the installation of the key concepts involved in numPy. Also, we will go through some of the practical examples of NumPy library.

### Installing NumPy In Python

Before you use NumPy you must install the NumPy library as a prerequisite. It can be installed with

, with **conda**

, or with a package manager.**pip**

If you use

, you can install it with:**conda**

`conda install numpy`

If you use

, you can install it with:**pip**

`pip install numpy`

### Arrays in NumPy

Array in NumPy is a table of elements, all of the same type, indexed by a tuple of positive integers. In NumPy, the number of dimensions of the array is called the rank of the array. A tuple of integers giving the size of the array along each dimension is known as the shape of the array. An array class in NumPy is called as **ndarray**.

**Example**

- First of all import the numpy library

`import numpy as np`

- Creating an array object using
**np.array()**

```
array = np.array([
[1, 2, 3, 5, 6],
[2, 1, 5, 6, 7]
])
```

- Printing the array dimension using
**array.ndim**

`print("No. of dimensions of the array: ", array.ndim)`

Output:

No. of dimensions of the array: 2

- Printing the shape of the array using
**array.shape**

`print("Shape of the array: ", array.shape)`

Output:

Shape of the array: (2, 5)

- Printing the size of the array using
**array.size**. The size of the array means nothing but the total number of elements in the given array.

`print("Size of the array: ", array.size)`

Output:

Size of the array: 10

### Creating a NumPy Array

Arrays in NumPy can be created in multiple ways, with various number of Ranks, defining the size of the Array. Arrays can also be created with the use of various data types such as lists, tuples, etc.

**Example**:

- First of all import the numpy library

`import numpy as np`

- Creating a rank 1 array by passing one python list

```
list = [1, 2, 3, 5, 6]
array = np.array(list)
print(array)
```

Output:

[1 2 3 5 6]

- Creating a rank 2 array by passing two python lists

```
list1 = [1, 2, 3, 5, 6]
list2 = [3, 1, 4, 5, 1]
array = np.array(
[list1, list2]
)
print(array)
```

Output:

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

- Creating array by passing a python tuple

```
tuple = (1, 2, 3, 5, 6)
array = np.array(tuple)
print(array)
```

Output:

[1 2 3 5 6]

- Creating a 3×4 array with all zeros using
**np.zeros( )**

```
array = np.zeros((3, 4))
print(array)
```

Output:

[[0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]]

- Creating a constant value array of complex type using
**np.full( )**

```
array = np.full((3, 3), 6, dtype='complex')
print(array)
```

Output:

[[6.+0.j 6.+0.j 6.+0.j] [6.+0.j 6.+0.j 6.+0.j] [6.+0.j 6.+0.j 6.+0.j]]

### NumPy Array Indexing

Indexing can be done in NumPy by using an array as an index. In case of slice, a view of the array is returned but in index array a copy of the original array is returned. Note that the first element is indexed by 0 second first by 1 and so on, whereas the last element is indexed by -1 second last by -2 and so on.

**Example**:

- Creating a rank 1 array by passing one python list

```
list = [1, 2, 3, 5, 6]
array = np.array(list)
print(array)
```

Output:

[1 2 3 5 6]

- Accessing elements and creating new array by passing indices

```
newArray = array[
np.array([2, 0, 1, 4])
]
print(newArray)
```

Output:

[3 1 2 6]

- Index values can be negative

```
newArray = array[
np.array([2, 0, -1, -4])
]
print(newArray)
```

Output:

[3 1 6 2]

- Basic slicing occurs when an object is a slice object that is of the form [start: stop: step].
**Note that stop position is not included in slicing.**

```
newArray = array[1:-2:1]
print(newArray)
```

Output:

[2 3]

### Basic slicing and indexing in a multidimensional array

Slicing and indexing in a multidimensional array are a little bit tricky compared to slicing and indexing in a one-dimensional array.

```
import numpy as np
array = np.array([
[2, 4, 5, 6],
[3, 1, 6, 9],
[4, 5, 1, 9],
[2, 9, 1, 7]
])
print(array)
# Slicing and indexing in 4x4 array
# Print first two rows and first two columns
print("\n", array[0:2, 0:2])
# Print all rows and last two columns
print("\n", array[:, 2:4])
# Print all column but middle two rows
print("\n", array[1:3, :])
```

Output:

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

### NumPy Operations on Array

In NumPy, arrays allow various operations that can be performed on a particular array or a combination of Arrays. These operations may include some basic Mathematical operations as well as Unary and Binary operations.

**Example**:

- Creating two different two dimensional arrays

```
array1 = np.array([
[2, 4, 5],
[3, 1, 6]
])
array2 = np.array([
[1, 5, 9],
[10, 32, 78]
])
```

- Adding 5 to every element in array1

```
newArray = array1 + 5
print(newArray)
```

Output:

[[ 7 9 10] [ 8 6 11]]

- Adding 5 to every element in array1

```
newArray = array1 + 5
print(newArray)
```

Output:

[[ 7 9 10] [ 8 6 11]]

- Multiplying 2 to every element in array2

```
newArray = array2 * 2
print(newArray)
```

Output:

[[ 2 10 18] [ 20 64 156]]

- Sum of every element in array2

```
newArray = array2.sum()
print(newArray)
```

Output:

135

- Adding two arrays

```
newArray = array1 + array2
print(newArray)
```

Output:

[[ 3 9 14] [13 33 84]]

## String Operations using NumPy

This module is used to perform vectorized string operations for arrays of dtype numpy.string_ or numpy.unicode_.

**numpy.upper( )**

Returns the uppercased string from the given string. It converts all lowercase characters to uppercase. If no lowercase characters exist, it returns the original string.

**Example**:

```
import numpy as np
string = "devopscube"
print(np.char.upper(string))
```

**Output**:

DEVOPSCUBE

Similary one can use **numpy.lower( )** to convert all uppercase characters to lowercase.

**numpy.split( )**

Returns a list of strings after breaking the given string by the specified separator.

**Example**:

```
import numpy as np
string = "devopscube.com"
print(np.char.split(string, sep='.'))
```

**Output**:

['devopscube', 'com']

**numpy.title( )**

It is used to convert the first character in each word to Uppercase and remaining characters to Lowercase in the string and returns a new string.

**Example**:

```
import numpy as np
string = "devopsCube is An amaZing pOrtal"
print(np.char.title(string))
```

**Output**:

Devopscube Is An Amazing Portal

**numpy.equal( )**

This function checks for string1 == string2 elementwise and return a boolean value true or false.

**Example**:

```
import numpy as np
string1 = "Devopscube"
string2 = "Devopscube.com"
print(np.char.equal(string1, string2))
```

**Output**:

False

To know more string functions in NumPy refer String operations.

## Mathematical Functions in NumPy

NumPy contains a large number of various mathematical operations. NumPy provides standard trigonometric functions, functions for arithmetic operations, handling complex numbers, etc.

**numpy.sin( )**

This mathematical function helps the user to calculate trigonometric **sine **for given values.

**Example**:

```
import numpy as np
x = 0
print(np.sin(x))
x = np.pi / 2
print(np.sin(x))
x = np.pi / 4
print(np.sin(x))
```

**Output**:

0.0 1.0 0.7071067811865475

Similarly one can use **numpy.cos( )**, **numpy.tan( )**, **numpy.arcsin( )**, **numpy.arccos( )**, **numpy.arctan( )** to calculate trignometric **cosine (cos), tangent (tan), cosecant (csc), secant (sec), and cotangent (cot)** respectively for given values.

**numpy.round_( )**

This mathematical function round an array to the given number of decimals.

**Example**:

```
import numpy as np
arr = [.33345, .1234, 1.456789]
roundOffValues = np.round_(arr, decimals=3)
print(roundOffValues)
```

**Output**:

[0.333 0.123 1.457]

**numpy.log( )**

This mathematical function helps users to calculate **Natural logarithm** of all elements in the input array.

**Example**:

```
import numpy as np
arr = [1, 3, 50]
logValues = np.log(arr)
print(logValues)
```

**Output**:

[0. 1.09861229 3.91202301]

**numpy.exp( )**

This mathematical function helps users to calculate the exponential of all elements in the input array.

**Example**:

```
import numpy as np
arr = [1, 3, 50]
expValues = np.exp(arr)
print(expValues)
```

**Output**:

[2.71828183e+00 2.00855369e+01 5.18470553e+21]

To know more mathematical functions in NumPy refer Mathematical functions.

## NumPy Use Cases in Data Science & Machine Learning

NumPy is a very popular Python library for large multi-dimensional array and matrix processing. With the help of a large collection of high-level mathematical functions it is very useful for fundamental scientific computations in Machine Learning.

It is particularly useful for,

- Linear Algebra
- Fourier Transform
- Random Number Generations

High-end libraries like TensorFlow uses NumPy internally for manipulation of Tensors.

### NumPy Linear Algebra Examples

Lots of ML concepts are tied up with linear algebra. It helps in

- To understand PCA(Principal Component Analysis),
- To build better ML algorithms from scratch,
- For processing Graphics in ML,
- It helps to understand Matrix factorization.

In fact, it could be said that ML completely uses matrix operations.

The Linear Algebra module of NumPy offers various methods to apply linear algebra on any NumPy array. One can find:

- Rank, determinant, transpose, trace, inverse, etc. of an array.
- Eigenvalues and eigenvectors of the given matrices
- The dot product of two scalar values, as well as vector values.
- Solve a linear matrix equation and much more!

Lets looks at some NumPy sample exercises

**1.** **Find rank, determinant, transpose, trace, inverse, etc. of an array using Numpy**

**Example**:

- Creating a 3×3 NumPy array

```
array = np.array([
[6, 1, 1],
[4, -2, 5],
[2, 8, 7]
])
```

- Calculating rank of array

```
rank = np.linalg.matrix_rank(array)
print(rank)
```

Output:

3

- Calculating determinant of array

```
determinant = np.linalg.det(array)
print(determinant)
```

Output:

-306.0

- Calculating trace of array

```
trace = np.trace(array)
print(trace)
```

Output:

11

- Calculating transpose of array

```
transpose = np.transpose(array)
print(transpose)
```

Output:

[[ 6 4 2] [ 1 -2 8] [ 1 5 7]]

- Calculating inverse of array

```
inverse = np.linalg.inv(array)
print(inverse)
```

Output:

[[ 0.17647059 -0.00326797 -0.02287582] [ 0.05882353 -0.13071895 0.08496732] [-0.11764706 0.1503268 0.05228758]]

**2**. **Find eigenvalues and eigenvectors of the given matrices using NumPy**

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

Output:

[ 1.61168440e+01 -1.11684397e+00 -1.30367773e-15]

[[-0.23197069 -0.78583024 0.40824829]

[-0.52532209 -0.08675134 -0.81649658]

[-0.8186735 0.61232756 0.40824829]]

**3. Find the dot product of two scalar values and vector values using NumPy**

```
import numpy as np
scalarProduct = np.dot(6, 9)
print("Dot Product of scalar values : ", scalarProduct)
vector_a = 4 + 3j
vector_b = 2 + 6j
vectorProduct = np.dot(vector_a, vector_b)
print("Dot Product of vector values : ", vectorProduct)
```

Output:

Dot Product of scalar values : 54 Dot Product of vector values : (-10+30j)

**4. Solve a linear matrix equation using Numpy**

```
import numpy as np
A = np.array([
[1, 3],
[2, 4]
])
b = np.array([
[7],
[10]
])
x = np.linalg.solve(A, b)
print(x)
```

Output:

[[1.]

[2.]]

### NumPy **Fourier Transform** Examples

In mathematics, a **Fourier transform** (**FT**) is a mathematical transform that decomposes a function (often a function of time, or a signal) into its constituent frequencies. Some of the important applications of the FT include:

- Fast large-integer and polynomial multiplication,
- Efficient matrix-vector multiplication for Toeplitz, circulant and other structured matrices,
- Filtering algorithms,
- Fast algorithms for discrete cosine or sine transform (e.g. Fast Discrete Cosine Transform used for JPEG and MPEG/MP3 encoding and decoding),
- Solving difference equations.

**Example**:

- Using
**np.fft( )**, get the 1D Fourier Transform

```
import numpy as np
A = np.array([2, 4, 6, 8, 9])
result = np.fft.fft(A)
print(result)
```

Output:

[29. +0.j -5.30901699+5.93085309j -4.19098301+1.03681323j -4.19098301-1.03681323j -5.30901699-5.93085309j]

- Using
**np.fft2( )**, get the 2D Fourier Transform

```
import numpy as np
A = np.array([
[2, 4, 6, 8, 9],
[3, 1, 6, -2, -4]
])
result = np.fft.fft2(A)
print(result)
```

Output:

[[ 33. +0.j -6.47213595 -3.52671151j 2.47213595 +5.7063391j 2.47213595 -5.7063391j -6.47213595 +3.52671151j] [ 25. +0.j -4.14589803+15.38841769j -10.85410197 -3.63271264j -10.85410197 +3.63271264j -4.14589803-15.38841769j]]

- Using
**np.fftn( )**, get the N-D Fourier Transform

```
import numpy as np
A = np.array([
[2.3, 4.1, 6.5, 8, 9],
[3, -1.2, 6, -2, -4]
])
result = np.fft.fftn(A)
print(result)
```

Output:

[[ 31.7 +0.j -7.22558014 -1.82338546j 4.62558014 +7.41621639j 4.62558014 -7.41621639j -7.22558014 +1.82338546j] [ 28.1 +0.j -3.53966744+12.90709507j -12.26033256 -4.50909046j -12.26033256 +4.50909046j -3.53966744-12.90709507j]]

### NumPy **Random Number Generations**

Using **numpy.random.rand(d0, d1, …., dn ) **creates an array of specified shape and fills it with random values, where d0, d1, …., dn are dimensions of the returned array. This function returns an array of defined shape and filled with random values.

**Example**:

- Randomly constructing 1D array

```
import numpy as np
A = np.random.rand(7)
print(A)
```

Output:

[0.3126664 0.99492257 0.73164575 0.77857217 0.94840314 0.10833222 0.14896065]

- Randomly constructing 2D array

```
import numpy as np
A = np.random.rand(3, 4)
print(A)
```

Output:

[[0.22751116 0.09730939 0.97083485 0.67629309] [0.94896123 0.96087311 0.8725199 0.48835455] [0.86496409 0.32296315 0.72891428 0.27729306]]

## Conclusion

In this python Numpy tutorial, I have covered the key concepts with some practical examples pertaining to Machine learning use cases.

If you want to have a look at more Numpy practical examples, you can check out the practical NumPy examples.

Now, I would like to hear from you. What Numpy use cases are you currently working on?