Unit 1
Unit 1
•Numerical Python
• General-purpose array-processing package.
• High-performance multidimensional array object, and tools for
working with these arrays.
• Fundamental package for scientific computing with Python.
• It is open-source software.
NumPy - Features
Output:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12, 13, 14, 15, 16, 17, 18, 19])
1. Using the NumPy functions
Output:
array([ 0 1 2 3 4 5 6 7 8 9 10 1112 13 14,15, 16, 17, 18, 19])
1. Using the NumPy functions
Output:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19]])
1. Using the NumPy functions
Output:
array([[0., 0., 0., 0.],
[0., 0., 0., 0.]])
array([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])
1. Using the NumPy functions
1. Using the NumPy functions
1. Using the NumPy functions
[[0. 0. 0. 0.]
[0. 0. 0. 0.]]
c. Using other NumPy functions
import numpy as np [[1. 1. 1. 1. 1. 1.]
a=np.zeros((2,4)) [1. 1. 1. 1. 1. 1.]
b=np.ones((3,6)) [1. 1. 1. 1. 1. 1.]]
c=np.empty((2,3))
[[1.14137702e-316 0.00000000e+000
d=np.full((2,2), 3) 6.91583610e-310]
e= np.eye(3,3) [6.91583609e-310 6.91583601e-310
f=np.linspace(0, 10, num=4) 6.91583601e-310]]
print(a) [[3 3]
[3 3]]
print(b)
print(c) [[1. 0. 0.]
print(d) [0. 1. 0.]
[0. 0. 1.]]
1 empty_like() Return a new array with the same shape and type
2 ones_like() Return an array of ones with the same shape and type.
3 zeros_like() Return an array of zeros with the same shape and type
4 full_like() Return a full array with the same shape and type
import numpy as np
[4 5 6]
array=np.array([4,5,6]) print(array)
[4, 5, 6]
list=[4,5,6]
print(list)
Working with Ndarray
• np.ndarray(shape, type)
• Creates an array of the given shape with random numbers.
• np.array(array_object)
• Creates an array of the given shape from the list or tuple.
• np.zeros(shape)
• Creates an array of the given shape with all zeros.
• np.ones(shape)
• Creates an array of the given shape with all ones.
• np.full(shape,array_object, dtype)
• Creates an array of the given shape with complex numbers.
• np.arange(range)
• Creates an array with the specified range.
NumPy Basic Array Operations
There is a vast range of built-in operations that we can perform on
these arrays.
1. ndim – It returns the dimensions of the array.
2. itemsize – It calculates the byte size of each element.
3. dtype – It can determine the data type of the element.
4. reshape – It provides a new view.
5. slicing – It extracts a particular set of elements.
6. linspace – Returns evenly spaced elements.
7. max/min , sum, sqrt
8. ravel – It converts the array into a single line.
Arrays in NumPy
Checking Array Dimensions in NumPy
import numpy as np
a = np.array(10)
b = np.array([1,1,1,1])
c = np.array([[1, 1, 1], [2,2,2]])
d = np.array([[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]) print(a.ndim) #0
print(b.ndim) #1
print(c.ndim) #2
print(d.ndim) #3
Higher Dimensional Arrays in NumPy
import numpy as np
arr = np.array([1, 1, 1, 1, 1], ndmin=10)
print(arr)
print('number of dimensions :', arr.ndim)
[[[[[[[[[[1 1 1 1 1]]]]]]]]]]
number of dimensions : 10
Indexing and Slicing in NumPy
Indexing & Slicing
Indexing
import numpy as np
arr=([1,2,5,6,7])
print(arr[3]) #6
Slicing
import numpy as np
arr=([1,2,5,6,7])
print(arr[2:5]) #[5, 6, 7]
Indexing and Slicing
Indexing and Slicing in 2-D
Copying Arrays
Copy from one array to another
• Method 1: Using np.empty_like() function
• Method 2: Using np.copy() function
• Method 3: Using Assignment Operator
Using np.empty_like( )
• This function returns a new array with the same shape and type as a
given array.
Syntax:
• numpy.empty_like(a, dtype = None, order = ‘K’, subok = True)
Using np.empty_like( )
import numpy as np
ary = np.array([13, 99, 100, 34, 65, 11, 66, 81, 632, 44])
import numpy as np
org_array = np.array([[99, 22, 33],[44, 77, 66]])
# Copying org_array to copy_array using Assignment operator
copy_array = org_array
# modifying org_array
org_array[1, 2] = 13
import numpy as np
for x in arr:
print(x)
Output:
[1 2 3]
[4 5 6]
Iterating Arrays
• To return the actual values, the scalars, we have to iterate the arrays
in each dimension.
arr = np.array([[1, 2, 3], [4, 5, 6]])
for x in arr:
for y in x:
print(y)
1
2
3
4
5
6
Iterating Arrays
• import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
for x in arr:
print(x)
[[1 2 3] [4 5 6]]
[[ 7 8 9] [10 11 12]]
Iterating Arrays
import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
for x in arr:
for y in x:
for z in y:
print(z)
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
for x in np.nditer(arr):
print(x)
Identity array
• The identity array is a square array with ones on the main diagonal.
• The identity() function return the identity array.
Identity
• Parameters:
• n : [int] Dimension n x n of output array
• dtype : [optional, float(by Default)] Data type of returned array
Identity array
Output:
Matrix b :
[[ 1. 0.]
[ 0. 1.]]
Matrix a :
[[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]
[ 0. 0. 1. 0.]
[ 0. 0. 0. 1.]]
eye( )
• numpy.eye(R, C = None, k = 0, dtype = type <‘float’>) : Return a
matrix having 1’s on the diagonal and 0’s elsewhere w.r.t. k.
• R : Number of rows
C : [optional] Number of columns; By default M = N
k : [int, optional, 0 by default]
Diagonal we require; k>0 means diagonal above main diagonal or
vice versa.
dtype : [optional, float(by Default)] Data type of returned array.
eye( )
Identity( ) vs eye( )
import numpy as np
print(np.eye(3,5,1))
print(np.eye(8,4,0))
print(np.eye(8,4,-1))
print(np.eye(8,4,-2))
Print(np.identity(4)
Shape of an Array
• import numpy as np
print(arr.shape)
• Output: (2,4)
Reshaping arrays
• import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(4, 3)
print(newarr)
• Output:
• [[ 1 2 3]
• [ 4 5 6]
• [ 7 8 9]
• [10 11 12]]
Reshape From 1-D to 3-D
• The outermost dimension will have 2 arrays that contains 3 arrays, each with 2 elements
• import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(2, 3, 2)
print(newarr)
Output:
[[[ 1 2]
[ 3 4]
[ 5 6]]
[[ 7 8]
[ 9 10]
[11 12]]]
Can we Reshape into any Shape?
• Yes, as long as the elements required for reshaping are equal in both
shapes.
• We can reshape an 8 elements 1D array into 4 elements in 2 rows 2D array
but we cannot reshape it into a 3 elements 3 rows 2D array as that would
require 3x3 = 9 elements.
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
newarr = arr.reshape(3, 3)
print(newarr)
[12 32 40]
[ 3 40 20]
[ 1 5 12]
[1 2 3]
128
[6 77 45]
[18 54 56]
3. NumPy Binary Operators
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[4, 3], [2, 1]])
print (a + b)
print (a*b)
[[5 5]
[5 5]]
[[4 6]
[6 4]]
NumPy Universal Functions
import numpy as np
a = np.array([0, np.pi/2, np.pi])
print ( np.sin(a))
a = np.array([0, 1, 2, 3])
print ( np.exp(a))
print ( np.sqrt(a))
import numpy as np
a = np.array([7,3,4,5,1])
b = np.array([3,4,5,6,7])
np.add(a, b) #([ 10, 7, 9, 11, 8])
np.subtract(a,b) #[ 4,-1,-1,-1,-6]
np.multiply(a, b) #[21, 12, 20, 30, 7]
np.divide(a, b) #[2.33333333, 0.75 , 0.8 , 0.83333333, 0.14285714]
np.remainder(a,b) #[1, 3, 4, 5, 1]
np.mod(a,b) #[1, 3, 4, 5, 1]
np.power(a,b) #[ 343, 81, 1024, 15625, 1]
np.reciprocal(a) #[0, 0, 0, 0, 1]
NumPy Add Operator
import numpy as np
a = np.array([10,20,100,200,500])
b = np.array([3,4,5,6,7])
print(a+b) #[ 13 24 105 206 507]
print(a-b)
print(a*b)
print(a/b)
Types of Array
Creating a 1-D Array
Creating a 1-D Array
Creation of a multidimensional
array(ndarray)
Creation of a multidimensional
array(ndarray)
Creation of a multidimensional
array(ndarray)
Program to illustrate Indexing in Ndarrays
Program to illustrate Indexing in Ndarrays
Program to illustrate Indexing in a 3D
array
Program to illustrate Indexing in a 3D
array
Operations on Ndarray
Operations on Ndarray
Add two 1d arrays element-wise
Add two 1d arrays element-wise
import numpy as np
x1: [1 2 0 3]
# create numpy arrays x1 and x2
x2: [4 1 2 2]
x1 = np.array([1, 2, 0, 3])
x3: [5 3 2 5]
x2 = np.array([4, 1,2, 2])
# elementwise sum with np.add()
x3 = np.add(x1, x2)
# display the arrays
print("x1:", x1)
print("x2:", x2)
print("x3:", x3)
x3 = x1 + x2
# display the arrays
print("x1:", x1)
print("x2:", x2)
print("x3:", x3)
Add two 2d arrays elementwise
# create 2d arrays x1 and x2 x1:
x1 = np.array([[1, 0, 1], [2, 1, 1], [3, 0, 3]]) [[1 0 1]
[2 1 1]
x2 = np.array([[2, 2, 0], [1, 0, 1], [0, 1, 0]])
[3 0 3]]
# elementwise sum with np.add() x2:
x3 = np.add(x1, x2) [[2 2 0]
[1 0 1]
# display the arrays print("x1:\n", x1) [0 1 0]]
print("x2:\n", x2) x3:
[[3 2 1]
print("x3:\n", x3)
[3 1 2]
[3 1 3]]
Add more than two arrays elementwise
# create numpy arrays x1, x2, and x3 x1: [1 3 0 7]
x1 = np.array([1, 3, 0, 7]) x2: [2 0 1 1]
x3: [0 1 3 1]
x2 = np.array([2, 0, 1, 1])
x4: [3 4 4 9]
x3 = np.array([0, 1, 3, 1])
# elementwise sum with +
x4 = x1+x2+x3
# display the arrays
print("x1:", x1)
print("x2:", x2)
print("x3:", x3)
print("x4:", x4)
NumPy Array attributes
1. ndarray.flags- It provides information about memory layout
2. ndarray.shape- Provides array dimensions
3. ndarray.strides- Determines step size while traversing the
arrays
4. ndarray.ndim- Number of array dimensions
5. ndarray.data- Points the starting position of array
6. ndarray.size- Number of array elements
7. ndarray.itemsize- Size of individual array elements in bytes
8. ndarray.base- Provides the base object, if it is a view
9. ndarray.nbytes- Provides the total bytes consumed by the
array
10. ndarray.T- It gives the array transpose
11. ndarray.real- Separates the real part
12. ndarray.imag- Separates the imaginary
NumPy Array attributes
1. ndarray.flags- It provides information about memory layout
2. ndarray.shape- Provides array dimensions
3. ndarray.strides- Determines step size while traversing the
arrays
4. ndarray.ndim- Number of array dimensions
5. ndarray.data- Points the starting position of array
6. ndarray.size- Number of array elements
7. ndarray.itemsize- Size of individual array elements in bytes
8. ndarray.base- Provides the base object, if it is a view
9. ndarray.nbytes- Provides the total bytes consumed by the
array
10. ndarray.T- It gives the array transpose
11. ndarray.real- Separates the real part
12. ndarray.imag- Separates the imaginary
Join, split, search and sort
Joining
import numpy as np
print(arr)
Output:[1 2 3 4 5 6]
Join two 2-D arrays along rows (axis=1)
import numpy as np
print(arr)
Output:[[1 2 5 6] [3 4 7 8]]
stack( )
import numpy as np
print(arr)
import numpy as np
print(arr)
Output: [1 2 3 4 5 6]
vstack( ) - Stacking Along Columns
• NumPy provides a helper function: vstack() to stack along columns.
import numpy as np
print(arr)
• split( )
• array_split( )
Split
• hsplit( )
• vsplit( )
Splitting
Note: We also have the method split() available but it will not adjust
the elements when elements are less in source array for splitting like
in example above, array_split() worked properly but split() would fail.
array_split( )
import numpy as np
newarr = np.array_split(arr, 3)
print(newarr)
Output:
[array([1, 2]), array([3, 4]), array([5, 6])]
split( )
import numpy as np
newarr = np.split(arr, 3)
print(newarr)
Output:
[array([1, 2]), array([3, 4]), array([5, 6])]
array_split( )
import numpy as np
newarr = np.array_split(arr, 4)
print(newarr)
import numpy as np
newarr = np.split(arr, 4)
print(newarr)
Output:
Error
Split Into Arrays
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
newarr = np.array_split(arr, 3)
print(newarr[0])
print(newarr[1])
print(newarr[2])
Output:[1 2] [3 4] [5 6]
Splitting 2-D Arrays
import numpy as np
arr = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
newarr = np.array_split(arr, 3)
print(newarr)
Output:[array([[1, 2], [3, 4]]), array([[5, 6], [7, 8]]), array([[ 9, 10], [11,
12]])]
hsplit( ) and vsplit( )
• hsplit is equivalent to split with axis=1, the array is always split along
the second axis regardless of the array dimension.
newarr = np.vsplit(arr, 3)
print(newarr)
Searching
• You can search an array for a certain value, and return the indexes
that get a match.
• To search an array, use the where() method.
Output:(array([3, 5, 6]),)
Sorting
• Sorting means putting elements in an ordered sequence.
• Ordered sequence is any sequence that has an order corresponding
to elements, like numeric or alphabetical, ascending or
descending.
• The NumPy ndarray object has a function called sort(), that will
sort a specified array.
• Note: This method returns a copy of the array, leaving the original
array unchanged.
import numpy as np
arr = np.array([3, 2, 0, 1])
print(np.sort(arr))
Output:[0 1 2 3]
Search
Array shape manipulation
Reshaping Array
List and Array
Linear Algebra with Numpy
Linear Algebra Module
A = np.array([[6, 1, 1],
[4, -2, 5],
[2, 8, 7]])
# Rank of a matrix
print("Rank of A:", np.linalg.matrix_rank(A))
# Trace of matrix A
print("\nTrace of A:", np.trace(A))
# Determinant of a matrix
print("\nDeterminant of A:", np.linalg.det(A))
# Inverse of matrix A
print("\nInverse of A:\n", np.linalg.inv(A))
Rank of A: 3
Trace of A: 11
Determinant of A: -306.0
Inverse of A:
[[ 0.17647059 -0.00326797 -0.02287582]
[ 0.05882353 -0.13071895 0.08496732]
[-0.11764706 0.1503268 0.05228758]]
• The Python Numpy linear algebra package can find the eigenvalues
and eigenvectors of a matrix.
• We calculate the eigenvalues and eigenvectors of the matrix
import numpy as np
from numpy import linalg as LA
A = np.array([[1,2,3],[3,2,1],[1,0,-1]])
w, v = LA.eig(A)
print(w)
[ 4.31662479e+00 -2.31662479e+00 3.43699053e-17] print(v)
[[ 0.58428153 0.73595785 0.40824829] [ 0.80407569 -0.38198836
-0.81649658] [ 0.10989708 -0.55897311 0.40824829]]
Eigen values and vectors
• Pseudorandom
• Computers work on programs, and programs are definitive set of
instructions. So it means there must be some algorithm to generate a
random number as well.
• If there is a program to generate random number it can be predicted,
thus it is not truly random.
• Random numbers generated through a generation algorithm are
called pseudo random.
Random
• Truerandom
• In order to generate a truly random number on our computers we
need to get the random data from some outside source. This outside
source is generally our keystrokes, mouse movements, data on
network etc.
• We do not need truly random numbers, unless its related to security
(e.g. encryption keys) or the basis of application is the randomness
(e.g. Digital roulette wheels).
Generate Random number
x = random.randint(100)
print(x)
Output:45
Generate Random Float
x = random.rand()
print(x)
Output:0.20589891226659818
Generate Random Array
• In NumPy we work with arrays, and you can use the two methods from the
above examples to make random arrays.
Integers
• The randint() method takes a size parameter where you can specify the
shape of an array.
Output:[61 66 32 13 16]
Data Distribution
• Data Distribution is a list of all possible values, and how often each
value occurs.
• Such lists are important when working with statistics and data
science.
• The random module offer methods that returns randomly generated
data distributions.
Random Distribution
• Generate a 1-D array containing 100 values, where each value has to
be 3, 5, 7 or 9.
• The probability for the value to be 3 is set to be 0.1
• The probability for the value to be 5 is set to be 0.3
• The probability for the value to be 7 is set to be 0.6
• The probability for the value to be 9 is set to be 0
print(x)
Example
[3 7 5 7 7 7 5 7 3 7 3 7 7 7 7 5 7 5 7 7 7 7 7 5 3 7 5 7 7 7 3 5 3 7 5 7 7 5
757577577353577577775753557773777757757
7 7 7 7 7 5 5 3 5 5 7 5 5 7 7 5 3 3 7 7 5 7 7]
Example
• You can return arrays of any shape and size by specifying the shape
in the size parameter.
• Same example as above, but return a 2-D array with 3 rows, each
containing 5 values.
[[7 7 7 7 7]
[5 3 5 7 5]
[5 7 5 7 5]]
Normal Distribution
Output:
Run1:
[[ 0.15001821 -1.31355388 -1.35020654] [-1.31067087 -0.48537757
-0.02052509]]
Run2:
[[-2.0610908 -0.3081812 0.99886608] [ 0.56001902 0.38363428
-0.07954767]]
Visualization of Normal Distribution
from numpy import random
import matplotlib.pyplot as plt
import seaborn as sns
sns.distplot(random.normal(size=1000), hist=False)
plt.show()
Exponential Distribution
• Exponential distribution is used for describing time till next event e.g.
failure/success etc.
• It has two parameters:
• scale - inverse of rate ( see lam in poisson distribution ) defaults to 1.0.
• size - The shape of the returned array.
Exponential Distribution
To solve this, we can start by knowing that the average time between customers is
two minutes. Thus, the rate can be calculated as:
• λ = 1/μ
• λ = 1/2
• λ = 0.5
• We can plug in λ = 0.5 and x = 1 to the formula for the CDF:
• P(X ≤ x) = 1 – e-λx
• P(X ≤ 1) = 1 – e-0.5(1)
• P(X ≤ 1) = 0.3935
The probability that we’ll have to wait less than one minute for the next customer
to arrive is 0.3935.
Exponential Distribution
• Draw out a sample for exponential distribution with 2.0 scale with
2x3 size:
print(x)
print(x)
Output:[5 7 6 5 4 7 5 4 6 5]
[5 3 6 4 3 3 3 5 5 5]
Visualization of Binomial Distribution
x = random.poisson(lam=2, size=10)
print(x)
Uniform Distribution
x = random.uniform(size=(2, 3))
print(x)
print(x)