INTRODUCTION OF NUMPY

Ravi shankar
11 min readJun 30, 2021

BY-RAVI SHANKAR

NumPy Linear Algebra

Numpy provides the following functions to perform the different algebraic calculations on the input data.

SNFunctionDefinition1dot()It is used to calculate the dot product of two arrays.2vdot()It is used to calculate the dot product of two vectors.3inner()It is used to calculate the inner product of two arrays.4matmul()It is used to calculate the matrix multiplication of two arrays.5det()It is used to calculate the determinant of a matrix.6solve()It is used to solve the linear matrix equation.7inv()It is used to calculate the multiplicative inverse of the matrix.

numpy.dot() function

This function is used to return the dot product of the two matrices. It is similar to the matrix multiplication. Consider the following example.

Example

import numpy as np

a = np.array([[100,200],[23,12]])

b = np.array([[10,20],[12,21]])

dot = np.dot(a,b)

print(dot)

Output:

[[3400 6200]
[ 374 712]]
The dot product is calculated as:[100 * 10 + 200 * 12, 100 * 20 + 200 * 21] [23*10+12*12, 23*20 + 12*21]

numpy.vdot() function

This function is used to calculate the dot product of two vectors. It can be defined as the sum of the product of corresponding elements of multi-dimensional arrays.

Consider the following example.

Example

import numpy as np

a = np.array([[100,200],[23,12]])

b = np.array([[10,20],[12,21]])

vdot = np.vdot(a,b)

print(vdot)

Output:

5M

76

Triggers in SQL (Hindi)

5528
np.vdot(a,b) = 100 *10 + 200 * 20 + 23 * 12 + 12 * 21 = 5528

numpy.inner() function

This function returns the sum of the product of inner elements of the one-dimensional array. For n-dimensional arrays, it returns the sum of the product of elements over the last axis.

Consider the following example.

Example

import numpy as np

a = np.array([1,2,3,4,5,6])

b = np.array([23,23,12,2,1,2])

inner = np.inner(a,b)

print(inner)

Output:

130

numpy.matmul() function

It is used to return the multiplication of the two matrices. It gives an error if the shape of both matrices is not aligned for multiplication. Consider the following example.

Example

import numpy as np

a = np.array([[1,2,3],[4,5,6],[7,8,9]])

b = np.array([[23,23,12],[2,1,2],[7,8,9]])

mul = np.matmul(a,b)

print(mul)

numpy determinant

The determinant of the matrix can be calculated using the diagonal elements. The determinant of following 2 X 2 matrix

A B
C D

can be calculated as AD — BC.

The numpy.linalg.det() function is used to calculate the determinant of the matrix. Consider the following example.

Example

import numpy as np

a = np.array([[1,2],[3,4]])

print(np.linalg.det(a))

Output:

-2.0000000000000004

numpy.linalg.solve() function

This function is used to solve a quadratic equation where values can be given in the form of the matrix.

The following linear equations

  1. 3X + 2 Y + Z = 10
  2. X + Y + Z = 5

can be represented by using three matrices as:

3 2 1

1 1 1

X

Y

Z and

10

5.

The two matrices can be passed into the numpy.solve() function given as follows.

Example

import numpy as np

a = np.array([[1,2],[3,4]])

b = np.array([[1,2],[3,4]])

print(np.linalg.solve(a, b))

Output:

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

numpy.linalg.inv() function

This function is used to calculate the multiplicative inverse of the input matrix. Consider the following example.

Example

import numpy as np

a = np.array([[1,2],[3,4]])

print(“Original array:\n”,a)

b = np.linalg.inv(a)

print(“Inverse:\n”,b)

Output:

Original array:
[[1 2]
[3 4]]
Inverse:
[[-2. 1. ]
[ 1.5 -0.5]]

Using NumPy Arrays

For two arrays A and B of the same size, if we wanted to do a vector multiplication in Python:

c = []
for i in range(len(a)):
c.append(a[i]*b[i])

In numpy, this can simply be done with the following line of code:

c = a*b

The indexes in NumPy arrays start with 0, meaning that the first element has index 0, and the second has index 1 etc.

Example

Get the first element from the following array:

import numpy as np

arr = np.array([1, 2, 3, 4])

print(arr[0])

Example

Get the second element from the following array.

import numpy as np

arr = np.array([1, 2, 3, 4])

print(arr[1])

Example

Get third and fourth elements from the following array and add them.

import numpy as np

arr = np.array([1, 2, 3, 4])

print(arr[2] + arr[3])

Access 2-D Arrays

To access elements from 2-D arrays we can use comma separated integers representing the dimension and the index of the element.

Example

Access the 2nd element on 1st dim:

import numpy as np

arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])

print(‘2nd element on 1st dim: ‘, arr[0, 1])

Example

Access the 5th element on 2nd dim:

import numpy as np

arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])

print(‘5th element on 2nd dim: ‘, arr[1, 4])

Access 3-D Arrays

To access elements from 3-D arrays we can use comma separated integers representing the dimensions and the index of the element.

Example

Access the third element of the second array of the first array:

import numpy as np

arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])

print(arr[0, 1, 2])

Vectorized Operations in NumPy

Numpy arrays are homogeneous in nature means it is an array that contains data of a single type only. Python’s lists and tuples, which are unrestricted in the type of data they contain. The concept of vectorized operations on NumPy allows the use of more optimal and pre-compiled functions and mathematical operations on NumPy array objects and data sequences. The Output and Operations will speed-up when compared to simple non-vectorized operations.

Example 1 : Using vectorized sum method on NumPy array. We will compare the vectorized sum method along with simple non-vectorized operation i.e the iterative method to calculate the sum of numbers from 0–14,999.

# importing the modules

import numpy as np

import timeit

# vectorized sum

print(np.sum(np.arange(15000)))

print("Time taken by vectorized sum : ", end = "")

%timeit np.sum(np.arange(15000))

# itersative sum

total = 0

for item in range(0, 15000):

total += item

a = total

print("\n" + str(a))

print("Time taken by iterative sum : ", end = "")

%timeit a

Output :

The above example shows the more optimal nature of vectorized operations of NumPy when compared with non-vectorized operations. This means when computational efficiency is the key factor in a program and we should avoid using these simple operations, rather we should use NumPy vectorized functions.

What do we mean by NumPy Universal Functions?

NumPy Universal functions are in actual the mathematical functions. The NumPy mathematical functions in NumPy are framed as Universal functions. These Universal (mathematical NumPy functions) operate on the NumPy Array and perform element-wise operations on the data values.

The universal NumPy functions belong to the numpy.ufunc class in Python. Some of the basic mathematical operations are called internally when we invoke certain operators. For example, when we frame x + y, it internally invokes the numpy.add() universal function.

We can even create our own universal functions using frompyfunc() method.

Syntax:

numpy.frompyfunc(function-name, input, output)
  • function-name: name of the function to be framed as a universal function
  • input: The number of input arrays
  • output: The number of output arrays

Example:

In this example, we have converted the function product to a universal function using frompyfunc() method.

Thus, now the product() method behaves like a universal mathematical function and performs element-wise multiplication when arrays are passed to it as parameters.

import numpy as npdef product(a, b):
return a*b
product = np.frompyfunc(product, 2, 1)res = product([1, 2, 3, 4], [1,1,1,1])
print(res)

Output:

[1 2 3 4]

1. Universal Trigonometric Functions in NumPy

In the course of this concept, we will now be have a look at some of the Universal Trigonometric Functions in NumPy.

  1. numpy. deg2raf(): This function helps us convert degree value to radians.
  2. numpy.sinh() function: Calculates the hyperbolic sine value.
  3. numpy.sin() function: Calculates the inverse of the sine hyperbolic value.
  4. numpy.hypot() function: Calculates the hypotenuse for the right angled triangle structure.

Example:

import numpy as npdata = np.array([0, 30, 45])rad = np.deg2rad(data)# hyperbolic sine value
print('Sine hyperbolic values:')
hy_sin = np.sinh(rad)
print(hy_sin)
# inverse sine hyperbolic
print('Inverse Sine hyperbolic values:')
print(np.sin(hy_sin))
# hypotenuse
b = 3
h = 6
print('hypotenuse value for the right angled triangle:')
print(np.hypot(b, h))

Output:

Sine hyperbolic values:
[0. 0.54785347 0.86867096]
Inverse Sine hyperbolic values:
[0. 0.52085606 0.76347126]
hypotenuse value for the right angled triangle:
6.708203932499369

2. Universal Statistical functions

Apart from Trigonometric functions, Python NumPy also offers us Universal Statistical functions. Some of them are listed below:

  1. numpy.amin() function: Represents the minimum value from the array.
  2. numpy.amax() function: Represents the maximum value from the array.
  3. numpy.ptp() function: It represents the range of values of an array across an axis which is calculated by subtracting the minimum value from the maximum value.
  4. numpy.average() function: It calculates the average of the array elements.

Example:

import numpy as npdata = np.array([10.2,34,56,7.90])print('Minimum and maximum data values from the array: ')
print(np.amin(data))
print(np.amax(data))
print('Range of the data: ')
print(np.ptp(data))
print('Average data value of the array: ')
print(np.average(data))

Output:

Minimum and maximum data values from the array:
7.9
56.0
Range of the data:
48.1
Average data value of the array:
27.025000000000002

Broadcasting and Shape Manipulation

Broadcasting in NumPy:

The term broadcasting refers to the ability of NumPy to treat arrays of different shapes during arithmetic operations. Arithmetic operations on arrays are usually done on corresponding elements. If two arrays are of exactly the same shape, then these operations are smoothly performed.

Broadcasting provides a means of vectorizing array operations so that looping occurs in C instead of Python as we know that Numpy implemented in C. It does this without making needless copies of data and which leads to efficient algorithm implementations. There are cases where broadcasting is a bad idea because it leads to inefficient use of memory that slow down the computation.

NumPy operations are usually done on pairs of arrays on an element-by-element basis. In the simplest case, the two arrays must have exactly the same shape, as in the following example:

>>> a = np.array([1.0, 2.0, 3.0])
>>> b = np.array([2.0, 2.0, 2.0])
>>> a * b
array([ 2., 4., 6.])

If the dimensions of two arrays are dissimilar, element-to-element operations are not possible. However, operations on arrays of non-similar shapes is still possible in NumPy, because of the broadcasting capability. The smaller array is broadcast to the size of the larger array so that they have compatible shapes.

Rules for Broadcasting:

Broadcasting is possible if the following rules are satisfied −

  • Array with smaller ndim than the other is prepended with ‘1’ in its shape.
  • Size in each dimension of the output shape is maximum of the input sizes in that dimension.
  • An input can be used in calculation, if its size in a particular dimension matches the output size or its value is exactly 1.
  • If an input has a dimension size of 1, the first data entry in that dimension is used for all calculations along that dimension.

A set of arrays is said to be broadcastable if the above rules produce a valid result and one of the following is true −

  • Arrays have exactly the same shape.
  • Arrays have the same number of dimensions and the length of each dimension is either a common length or 1.
  • Array having too few dimensions can have its shape prepended with a dimension of length 1, so that the above stated property is true.

Let’s have a look on the following example to understand Broadcasting:

>>> from numpy import array
>>> a = array([[ 0.0, 0.0, 0.0],
... [10.0, 10.0, 10.0],
... [20.0, 20.0, 20.0],
... [30.0, 30.0, 30.0]])
>>> b = array([0.0, 1.0, 2.0])
>>> a + b
array([[ 0., 1., 2.],
[ 10., 11., 12.],
[ 20., 21., 22.],
[ 30., 31., 32.]])

As shown in fig.1, b is added to each row of a. When b is longer than the rows of a, as in fig.2 , an exception is raised because of the incompatible shapes.

fig.1: A two dimensional array multiplied by a one dimensional array results in broadcasting if number of 1-d array elements matches the number of 2-d array columns.

fig.2 When the trailing dimensions of the arrays are unequal, broadcasting fails because it is impossible to align the values in the rows of the 1st array with the elements of the 2nd arrays for element-by-element addition.

Limitations of Broadcasting

1️ Broadcasting is a handy shortcut that proves very useful in practice when working with NumPy arrays.

2️ That being said, it does not work for all cases, and in fact imposes a strict rule that must be satisfied for broadcasting to be performed.

3️ Arithmetic, including broadcasting, can only be performed when the shape of each dimension in the arrays are equal or one has the dimension size of 1.

Shape Manipulation in NumPy:

Numpy provides flexible tools to change the dimension of an array. Before changing the dimension, it is better to remember what dimension of an array means and how arrays with different dimension look like:

# 2-dimensional
b = np.zeros((3,4))b
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
b.ndim
2
# 3-dimensional
c = np.ones((2,2,2))
array([[[1., 1.],
[1., 1.]],

[[1., 1.],
[1., 1.]]])
c.ndim
3

There are different ways to change the dimension of an array. Reshape function is commonly used to modify the shape and thus the dimension of an array. We just need to pass the new shape as an argument to reshape function:

np.arange(8).reshape(2,2,2)
array([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])

Changing array shape:

1️ reshape(a, newshape[, order]) →Gives a new shape to an array without changing its data.

2️ ravel(a[, order]) →Return a contiguous flattened array.

3️ ndarray.flat →A 1-D iterator over the array.

4️ ndarray.flatten([order]) →Return a copy of the array collapsed into one dimension.

A boolean mask

Indexing and slicing are quite handy and powerful in NumPy, but with the booling mask it gets even better! Let’s start by creating a boolean array first. Note that there is a special kind of array in NumPy named a masked array. Here, we are not talking about it but we’re also going to explain how to extend indexing and slicing with NumPy Arrays:

In [58]: x = np.array([1,3,-1, 5, 7, -1]) 
In [59]: mask = (x < 0)
In [60]: mask
Out[60]: array([False, False, True, False, False, True], dtype=bool)

We can see from the preceding example that by applying the < logic sign that we applied scalars to a NumPy Array and the naming of a new array to mask, it's still vectorized and returns the True/False boolean with the same shape of the variable x indicated which element in x meet the criteria:

In [61]: x [mask] = 0 
In [62]: x
Out[62]: array([1, 3, 0, 5, 7, 0])

Using the mask, we gain the ability to access or replace any element value in our array..

--

--