What is NumPy?
NumPy is a Python library used for working with arrays. It also has functions for working in the domain of linear algebra, Fourier transform, and matrices. NumPy was created in 2005 by Travis Oliphant. It is an open-source project and you can use it freely. NumPy stands for Numerical Python.

Why Use NumPy?
In Python, we have 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 than traditional Python lists. The array object in NumPy is called ndarray, 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.

Why is NumPy Faster Than Lists?
NumPy arrays are stored at one continuous place in memory unlike lists, so processes can access and manipulate them very efficiently. This behaviour is called locality of reference in computer science. This is the main reason why NumPy is faster than lists. Also, it is optimized to work with the latest CPU architectures.

Which Language is NumPy written in?
NumPy is a Python library and is written partially in Python, but most of the parts that require fast computation are written in C or C++.

Below are some basic operations, which can be performed using NumPy in Python:

import numpy as np
mylist = [1,2,3]
type(mylist)

myarray = np.array(mylist)
type(myarray)

np.arange(0,10)

#2D array of zeros and ones
np.zeros(shape=(5,5))
np.ones(shape=(2,4))

np.random.seed(101)
arr = np.random.randint(0,100,10)
arr

arr2 = np.random.randint(0,100,10)
arr2

#Max Value and its location
arr.max()
arr.argmax()

#Min Value and its location
arr.min()
arr.argmin()

#Average of Array
arr.mean()

#Shape Array
arr.shape

#Reshape Array
arr.reshape(2,5)
mat = np.arange(0,100).reshape(10,10)
mat.shape

#indexing in Array
mat[0,1]
mat[4,6]
mat[:,1] #All the items in the column 1
mat[:,1].reshape(10,1) 
mat[2,:] #All items in the row 2

#Slicing Array in Python
mat[0:3, 0:3] #Get all the rows upto 3 and get all the column upto 3

#Assigning value 0 to the cutted slice
mat[0:3, 0:3] = 0
mynewmat = mat.copy()
mynewmat

mynewmat[0:6,:] = 999
mynewmat

Below is the code, in which a signature image is manipulated using NumPy and Python:

import numpy as np
import matplotlib.pyplot as plt

from PIL import Image

pic = Image.open('signature.jpeg')
type(pic)

#Convert Signature Image to Numpy Array
pic_arr = np.asarray(pic)
type(pic_arr)
pic_arr.shape

#Show Array Transformed Image
plt.imshow(pic_arr)

#Show Signature Image in Red Channel
pic_red = pic_arr.copy()
pic_red.shape

#R=0 G=1 B=2
plt.imshow(pic_red[:,:,1])
pic_red[:,:,1]

#Convert to Gray - Red Channel Values 0 (no red, pure black) -255 (full pure red)
plt.imshow(pic_red[:,:,0], cmap='gray') #closer, more red

#Convert to Gray - Green Channel Values 0-255
plt.imshow(pic_red[:,:,1], cmap='gray')

#Convert to Gray - Blue Channel Values 0-255
plt.imshow(pic_red[:,:,2], cmap='gray')

#Remove contribution of Green Channel
pic_red[:,:,1] = 0
plt.imshow(pic_red)

#Remove contribution of Red Channel
pic_red[:,:,0] = 0
plt.imshow(pic_red)

#Remove contribution of Blue Channel
pic_red[:,:,2] = 0
plt.imshow(pic_red)

pic_red.shape #3 Channel
pic_red[:,:,1].shape #1 Channel