Numerical NumPy, commonly known as NumPy, is a significant library among Python’s numerous libraries. It is widely used for various types of numerical and scientific computing. It is unparalleled for working with multi-dimensional arrays. Let’s first see how we can install NumPy:

## Installing NumPy

Installing NumPy on your system is very easy. If your computer has an internet connection, you can easily install it using the pip command below.

```
pip install numpy
```

If you use the command line, open the Python terminal and type this command to see NumPy being installed. If everything is done correctly, you will see something like the following:

The above command will install the latest version. If you want to install a specific version, you can specify the version number. However, it’s always best to use the latest version. For instance, if you want to install NumPy version 1.26.0, the pip command would be:

```
pip install numpy==1.26.0
```

## What is pip?

By now, you might be wondering what pip stands for. Pip is Python’s package manager. Packages that don’t come by default with Python can generally be installed using the pip command. These packages include all the files required for a module to work successfully and are typically indexed on the website https://pypi.org/. PyPI stands for Python Package Index. You can easily find any package or module by searching on this site.

The general rule for installing a package is:

```
pip install package_name
```

And for uninstalling:

```
pip uninstall package_name
```

## Installing NumPy Using an IDE

If you use any IDE (like PyCharm, Spyder), you will find an IPython Console in any window. By running the above code there, NumPy will be installed. Below is a visual explanation:

## NumPy Array

In NumPy, data is organized like an array. First, let’s see how to create an array:

```
import numpy as np #importing numpy
np_array=np.array([1,2,3]) #creating a numpy array
print(np_array)
```

Output:

```
[1 2 3]
```

In the first line, we imported NumPy as np. In the third line, np.array(([1, 2, 3])) is used to create a NumPy array. Here, 1, 2, and 3 are the elements of this array stored in a variable named np_array. The `print()`

function is used to display the array elements in the output.

Note: You might wonder why we used np. There is no compulsion to use an alias (Alias) when importing. For convenience in the program, using an alias helps avoid repeatedly writing the module’s full name, making the code cleaner. If we hadn’t used np, we would have written numpy.array([1, 2, 3]) in the third line.

The example above is a one-dimensional (1D) array.

### Converting List and Tuple to NumPy Variable

In previous chapters, we learned about Python’s various data structures, such as lists and tuples. These can easily be converted into NumPy variables. Instead of fixed numbers, we just need to give the variable names as in the example above.

```
import numpy as np
a=[10,20,40] #Declaring a list.
np_array_list=np.array(a)
b=(30,50,70) #Declaring a touple.
np_array_tuple=np.array(b)
print("The value of a is {} and type {}".format(a,type(a)))
print("The value of np_array is {} and type {}".format(np_array_list,type(np_array_list)))
print("The value of b is {} and type {}".format(b,type(b)))
print("The value of np_array is {} and type {}".format(np_array_tuple,type(np_array_tuple)))
```

Output:

```
The value of a is [10, 20, 40] and type <class 'list'>
The value of np_array is [10 20 40] and type <class 'numpy.ndarray'>
The value of b is (30, 50, 70) and type <class 'tuple'>
The value of np_array is [30 50 70] and type <class 'numpy.ndarray'>
```

### Two-Dimensional Array (2D)

In a 2D array, elements are arranged along the x and y axes. Let’s see an example:

```
import numpy as np #importing numpy
array_2D=np.array([[1,2,3],[4,5,6]]) #creating a 2D numpy array
print(array_2D)
```

Output:

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

We see a two-dimensional array as the output.

Note: A 2D array can represent a binary image. That is, a black and white image can be represented using a 2D array in NumPy.

### Three-Dimensional Array (3D)

By now, you might have guessed that in a 3D array, elements are arranged along the x, y, and z axes. Let’s see an example:

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

Output:

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

Here, a three-dimensional array is created.

A 3D array is used to represent complex three-dimensional objects.

### n-Dimensional Array (n-D)

Due to the limitations of our eyes, we can see objects up to 3D. Objects with more dimensions are not visible to us (scientists have researched how a 4-dimensional object looks and named it Tesseract). However, in programming, the dimensions can be increased to n.

Typically, when working with machine learning or deep learning models, there are billions of parameters, and n-D arrays are used to store these parameters.

## Accessing Specific Elements of an Array

To access a specific element of a NumPy array, we use the array’s index. The elements are arranged in an indexed manner, starting at 0. Let’s see an example:

```
import numpy as np #importing numpy
np_array=np.array([1,2,3]) #creating a numpy array
print(np_array)
np_array[0]=9 #Modifying the first element
print(np_array)
array_2D=np.array([[1,2,3],[4,5,6]]) #creating a 2D numpy array
print(array_2D[1][2])
```

Output:

```
[1 2 3]
[9 2 3]
6
```

In line 6, the first element of np_array is modified. When the array is printed again in line 7, its value is shown as [9 2 3]. Similarly, a 2D array value is modified and shown in line 9.

## NumPy Data Types

NumPy has some additional data types compared to Python’s default data types, represented by the first letter of the specific type, such as ‘b’ for boolean, ‘i’ for integer, ‘f’ for float, etc.

These new data types emerged to use computer memory more efficiently. For instance, to store very small numbers, we can use int2 (2 bytes = 16 bits), and for large numbers, we can use int8 (8 bytes = 64 bits). In small programs, these might not be significant, but when working with machine learning or deep learning datasets, even one byte can make a big difference.

Note: Unsigned data types can be used for numeric data types using ‘u’. Unsigned means no negative value can be stored.

### Creating Arrays with Specific Data Types

We can specify the data type of a variable while creating it.

```
import numpy as np
np_array = np.array([1, 2, 3], dtype='f')
print(np_array)
print(np_array.dtype)
```

Output:

```
[1. 2. 3.]
float32
```

Although 1, 2, 3 are integers in line 3, using dtype=’f’ converts them to 1. 2. 3., i.e., float.

## Array Operations

NumPy has some built-in methods to solve complex problems easily. Let’s see some commonly used methods with examples.

### Slicing an Array

Using the colon (:) operator, a specific part of a large array can be easily sliced. This operation is very useful and effective, especially during AI data pre-processing. The syntax is: `[start:end:step]`

. Let’s start with an example:

```
import numpy as np
np_array = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np_array[2:4]) #slicing elements from index 2 to 4
print(np_array[:4]) #slicing all elements from start to index 4
print(np_array[2:]) #slicing all elements from index 2 to end
print(np_array[2:9:2]) #slicing elements from index 2 to 9 with interval 2
```

Output:

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

In line 5, `2:4`

indicates the elements from index 2 to 4.

In line 7, `:4`

indicates all elements before index 4.

In line 9, `2:`

indicates all elements after index 2.

In line 11, `2:9:2`

indicates all elements from index 2 to 9 with an interval of 2.

To better understand, compare with the example.

### Changing Array Dimensions

To change an array from one dimension to another, we use the `reshape()`

method. For better understanding, let’s convert a 1D array to a 2D array:

```
import numpy as np
np_array = np.array([1, 2, 3, 4, 5, 6, 7, 8]) #1D array
np_array_new = np_array.reshape(2, 4) #2D array
print(np_array_new.shape)
print(np_array_new)
```

Output:

```
(2, 4)
[[1 2 3 4]
[5 6 7 8]]
```

In line 5, `.reshape(2,4)`

converts the 1D array to a 2D array with 2 rows and 4 columns. Those familiar with matrices can easily understand this.

In line 7, `.shape`

is used to print the shape of the reshaped array.

### Conditions for Dimension Conversion

To convert from one dimension to another, the number of elements must be equal. If we used (3,3) in the above example, an error would occur because the array has 8 elements, but the desired array would have 9 elements (3×3).

### Array Concatenation and Splitting

To concatenate multiple NumPy arrays, we use two functions: `concatenate()`

and `stack()`

. Let’s see an example:

```
import numpy as np
array1_2D = np.array([[1, 2], [3, 4]])
array2_2D = np.array([[5, 6], [7, 8]])
new_array = np.concatenate((array1_2D, array2_2D), axis=0)
new_array2 = np.concatenate((array1_2D, array2_2D), axis=0)
print(new_array)
```

Output:

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

In line 7, we use the `concatenate()`

function to concatenate a 2D NumPy array. The axis parameter is set to 0, indicating that the array will be concatenated row-wise. Setting it to 1 would concatenate column-wise.

The `concatenate()`

and `stack()`

functions perform similar tasks. The difference is that `concatenate()`

joins another array to the row or column of a NumPy array, while `stack()`

joins an array along a new axis. Let’s see an example:

```
import numpy as np
array1_2D = np.array([[1, 2], [3, 4]])
array2_2D = np.array([[5, 6], [7, 8]])
new_array = np.stack((array1_2D, array2_2D),axis=0)
print(new_array)
```

Output:

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

In line 7, the `stack()`

function is used. The output shows the main difference. `stack()`

has two more functions: `hstack()`

and `vstack()`

, which work similarly to the axis parameter of `concatenate()`

.

To split an array into multiple arrays, we use the `array_split()`

function. Let’s see an example:

```
import numpy as np
np_array = np.array([1, 2, 3, 4])
new_array = np.array_split(np_array, 2)
print(new_array)
print("Accessing array using index: ",new_array[0])
```

Output:

```
[array([1, 2]), array([3, 4])]
Accessing array using index: [1 2]
```

In line 5, we split an array into two arrays. An array can be easily accessed using the index, as shown in line 9.

### Loop

To access each element of a NumPy array, we use loops. Since we have already learned about loops, let’s not discuss it again but see an example:

```
import numpy as np
array_1D = np.array([1, 2]) #an 1D array
array_2D = np.array([[1, 2],[3,4]]) #a 2D array
for value in array_1D:
print(value)
print("2D array elements-")
for row in array_2D:
for col in row:
print(col)
```

Output:

```
1
2
2D array elements-
1
2
3
4
```

In line 6, we use a for loop to access and print the values of array_1D. A single for loop is sufficient for 1D. But for 2D, we use two loops. The first loop accesses the rows, and the second loop accesses the columns.

Note: Using a loop inside another loop is called a nested loop in programming. You can handle multiple nested loops if needed.

Note: To access multiple-dimensional arrays like 3D arrays, you will need three loops. Use as many loops as there are dimensions.

### where()

Using `where`

in NumPy, various operations can be easily performed on a specific element. Let’s see an example:

```
import numpy as np
np_array = np.array([1, 2, 3, 4])
new_array = np.where(np_array > 2)
print(new_array)
```

Output:

```
(array([2, 3], dtype=int64),)
```

In line 5, `np_array > 2`

indicates all numbers greater than 2.

## Some Essential NumPy Methods

Here are some essential methods discussed (alphabetically).

### absolute()

Used to find the absolute value of an array.

```
import numpy as np
np_array = [1, -2, -3]
new_array = np.absolute(np_array)
print(new_array)
```

Output:

```
[1 2 3]
```

### add()

The `add()`

method is used to add elements of a NumPy array element-wise.

```
import numpy as np
np_array1 = [1, 2, 3]
np_array2 = [4, 5, 6]
new_array = np.add(np_array1, np_array2)
print(new_array)
```

Output:

```
[5 7 9]
```

### arange()

This method is used to create new numbers within a specified range. It can be used in three ways: creating numbers from 0 to a specific number – `arange(number)`

; creating numbers from a specific number to another specific number – `arange(start,end)`

; and creating numbers from a specific number to another specific number at a specific interval – `arange(start,end,step)`

.

```
import numpy as np
np_array1 = np.arange(10)
np_array2 = np.arange(10,20)
np_array3 = np.arange(2, 3,.1)
print(np_array1)
print(np_array2)
print(np_array3)
```

Output:

```
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[2. 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9]
```

### ceil()

The `ceil()`

method converts a fractional number to the nearest highest integer.

```
import numpy as np
np_array = [1, 2.58646874, 3.2358979]
new_array = np.ceil(np_array)
print(new_array)
```

Output:

```
[1. 3. 4.]
```

### floor()

The `floor()`

method converts a fractional number to the nearest lowest integer.

```
import numpy as np
np_array = [1, 2.58646874, 3.2358979]
new_array = np.floor(np_array)
print(new_array)
```

Output:

```
[1. 2. 3.]
```

### multiply()

Used to multiply the elements of an array.

```
import numpy as np
np_array1 = [1, 2, 3]
np_array2 = [4, 5, 6]
new_array = np.multiply(np_array1, np_array2)
print(new_array)
```

Output:

```
[ 4 10 18]
```

### ones()

The `ones()`

method creates an array of a specified shape where each element’s value is one. Here, let’s see the process of creating a two-dimensional array.

```
import numpy as np
np_array = np.ones((2,3))
print(np_array)
```

Output:

```
[[1. 1. 1.]
[1. 1. 1.]]
```

Here, we see a 2×3 array where each element’s value is one.

### sort()

The `sort()`

method is used to sort the elements of a NumPy array in order. The algorithm used for sorting can be passed with the kind parameter. Properties of kind include quicksort, mergesort, heapsort, and stable. Let’s see an example:

```
import numpy as np
np_array = np.array([1, 5, 3, 7])
new_array = np.sort(np_array, kind='quicksort')
print(new_array)
```

Output:

```
[1 3 5 7]
```

We see that the unordered array is arranged in a specific order using the sort method.

Note: The kind parameter is optional and the array will be sorted even if it is not provided.

### subtract()

The `subtract()`

method is used to subtract one array from another.

```
import numpy as np
np_array1 = [1, 2, 3]
np_array2 = [4, 5, 6]
new_array = np.subtract(np_array2, np_array1)
print(new_array)
```

Output:

```
[3 3 3]
```

### zeros()

The `zeros()`

method creates an array of a specified shape where each element’s value is zero. Here, let’s see the process of creating a two-dimensional array.

```
import numpy as np
np_array = np.zeros((2,3))
print(np_array)
```

Output:

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

Here, we see a 2×3 array where each element’s value is zero.