NumPy is the fundamental package needed for scientific computing with Python. It contains:
a powerful N-dimensional array object basic linear algebra functions basic Fourier transforms sophisticated random number capabilities
Extra features: –fast, multidimensional arrays –libraries of reliable, tested scientific functions –plotting tools
**NumPy is at the core of nearly every scientific Python application or module since it provides a fast N-d array datatype that can be manipulated in a vectorized form.
Lists ok for storing small amounts of one-dimensional data. But, can’t use directly with arithmetical operators (+, -, *, /, …) Need efficient arrays with arithmetic and better multidimensional tools
Similar to lists, but much more capable, except fixed size NumPy is a hybrid of the older NumArray and Numeric packages , and is meant to replace them both.
NumPy adds a new data structure to Python – the ndarray. An N-dimensional array is a homogeneous collection of “items” indexed using N integers
Defined by: The shape of the array,kind of item the array is composed of.
In [2]:
import numpy as np
import numpy.matlib
Every ndarray is a homogeneous collection of exactly the same data-type every item takes up the same size block of memory each block of memory in the array is interpreted in exactly the same way.
Array Creation : There are a number of ways to initialize new numpy arrays, for example from – a Python list or tuples – using functions that are dedicated to generating numpy arrays, such as arange, linspace, etc. – reading data from files
In [12]:
# Eg : one dimensional
a = np.array([1,2,3,4])
print("One dim ")
print(a)
print(type(a))
#more than one dimension
b = np.array([[1, 2], [3, 4]])
print("Two dims")
print(b)
#using ndim
c=np.array([1,2,3,4,5], ndmin = 2)
print("Two dimensional")
print(c.ndim)
print(c.shape)
print(c)
#dtype:
np.array([1, 2, 3], dtype = complex)
Out[12]:
NumPy’s array class is called ndarray. It is also known by the alias array. Note that numpy.array is not the same as the Standard Python Library class array.array, which only handles one-dimensional arrays and offers less functionality.
ndarray.ndim the number of axes (dimensions) of the array. In the Python world, the number of dimensions is referred to as rank.This array attribute returns a tuple consisting of array dimensions.
In [5]:
arrey=np.array([[1,2,3],[4,5,6]])
arrey.ndim
print(arrey)
ndarray.shape the dimensions of the array. This is a tuple of integers indicating the size of the array in each dimension. For a matrix with n rows and m columns, shape will be (n,m). The length of the shape tuple is therefore the rank, or number of dimensions, ndim.
In [16]:
arrey = np.array([[1,2,3],[4,5,6]])
print(arrey)
print(arrey.shape)
#resize ndarray
arrey = np.array([[1,2,3],[4,5,6]])
arrey.shape = (3,2)
print(arrey)
#Resize: NumPy also provides a reshape function to resize an array.
barray = arrey.reshape(2,3)
print(barray)
ndarray.size : Total number of elements of the array. This is equal to the product of the elements of shape.
In [17]:
arrey.size
Out[17]:
ndarray.dtype : an object describing the type of the elements in the array. One can create or specify dtype’s using standard Python types. Additionally NumPy provides types of its own. numpy.int32, numpy.int16, and numpy.float64 are some examples.
In [18]:
arrey.dtype
Out[18]:
ndarray.iteamsize: This array attribute returns the length of each element of array in bytes.
In [20]:
#ax = np.array([1,2,3,4,5], dtype = np.int16)
ax = np.array([1,2,3,4,5], dtype = np.float32)
ax.itemsize
Out[20]:
ndarray.data the buffer containing the actual elements of the array. Normally, we won’t need to use this attribute because we will access the elements in an array using indexing facilities.
In [21]:
ax.data
Out[21]:
A dtype object is constructed using the following
syntax − numpy.dtype(object, align, copy)
Object − To be converted to data type object
Align − If true, adds padding to the field to make it similar to C-struct
Copy − Makes a new copy of dtype object. If false, the result is reference to builtin data type object.
In [2]:
dt = np.dtype(np.int32)
dt
Out[2]:
NumPy offers several functions to create arrays with initial placeholder content.
numpy.empty
Syntax: numpy.empty(shape, dtype = float, order = 'C')
Shape : Shape of an empty array in int or tuple of int
Dtype : Desired output data type. Optional
Order :'C' for C-style row-major array, 'F' for FORTRAN style column-major array
In [4]:
np.empty([3,3], dtype = int)
Out[4]:
numpy.zeros
Returns a new array of specified size, filled with zeros.
Syntax : numpy.zeros(shape, dtype = float, order = 'F')
In [5]:
print(np.zeros(5))
np.zeros((3,3))
Out[5]:
numpy.ones
Returns a new array of specified size and type, filled with ones.
Syntax : numpy.ones(shape, dtype = None, order = 'C')
In [6]:
np.ones(5)
Out[6]:
In [7]:
np.ones([2,2], dtype = int)
Out[7]:
Note: zeros_like,ones_like, empty_like arange,fromfunction, fromfile
numpy.asarray
This function is similar to numpy.array except for the fact that it has fewer parameters.
syntax : numpy.asarray(a, dtype = None, order = None)
In [8]:
x = [1,2,3]
a = np.asarray(x)
print(a)
print(type(a))
a.shape
Out[8]:
Numeric ranges
This function returns an ndarray object containing evenly spaced values within a given range.
syntax: numpy.arange(start, stop, step, dtype)
In [11]:
np.arange(5,9,2)
Out[11]:
numpy.linspace
This function is similar to arange() function. In this function, instead of step size, the number of evenly spaced values between the interval is specified.
syntax: numpy.linspace(start, stop, num, endpoint, retstep, dtype)
retstep : If true, returns samples and step between the consecutive numbers.
endpoint : True by default, hence the stop value is included in the sequence. If false, it is not included
In [13]:
np.linspace(10,20,num=5,endpoint=False,retstep=False)
Out[13]:
numpy.logspace
This function returns an ndarray object that contains the numbers that are evenly spaced on a log scale
syntax : numpy.logscale(start, stop, num, endpoint, base, dtype)
In [15]:
np.logspace(1.0, 2.0, num = 5)
Out[15]:
In [16]:
np.logspace(1.0, 2.0, num = 5,base=2)
Out[16]:
resize changes the shape and size of array in-place.
In [17]:
o = np.linspace(0, 4, 9)
print(o)
o.resize(3, 3)
o
Out[17]:
eye returns a 2-D array with ones on the diagonal and zeros elsewhere.
In [23]:
np.eye(2)
#import numpy.matlib
#np.matlib.eye(n = 3, M = 4, k = 0, dtype = float)
Out[23]:
diag extracts a diagonal or constructs a diagonal array.
In [24]:
y=[1,2,3]
np.diag(y)
Out[24]:
Create an array using repeating list (pythonic way)
In [25]:
#using numpy
np.repeat([1, 2, 3], 3)
Out[25]:
In [26]:
p = np.ones([2, 3], int)
p
Out[26]:
In [27]:
#vstack to stack arrays in sequence vertically (row wise).
np.vstack([p, 2*p])
Out[27]:
In [28]:
#hstack to stack arrays in sequence horizontally (column wise)
np.hstack([p, 2*p])
Out[28]:
In [29]:
s = np.arange(13)*2
s
Out[29]:
In [30]:
#indexing
s[0], s[4], s[-1]
Out[30]:
To indicate a range. array[start:stop] Leaving start or stop empty will default to the beginning/end of the array.
In [31]:
s[1:5]
Out[31]:
In [32]:
#Use negatives to count from the back.
s[-4:]
Out[32]:
In [34]:
#can be used to indicate step-size. array[start:stop:stepsize]
#Here we are starting 5th element from the end, and counting backwards by 2 until the beginning of the array is reached.
s[5::2]
Out[34]:
In [35]:
#Let's look at a multidimensional array.
m = np.arange(36)
m.resize((6, 6))
m
Out[35]:
In [36]:
#Use bracket notation to slice: array[row, column]
m[2, 2]
Out[36]:
In [37]:
#to select a range of rows or columns
m[3, 3:]
Out[37]:
In [40]:
#We can also perform conditional indexing. Here we are selecting values from the array that are greater than 30.
m[m > 30]
Out[40]:
In [41]:
#Here we are assigning all values in the array that are greater than 30 to the value of 30
m[m > 30] = 30
m
Out[41]:
In [42]:
x = np.arange(10)
print(x)
s=slice(2,7,2)
print("Done",x[s])
Math functions :NumPy contains a large number of various mathematical operations. NumPy provides standard trigonometric functions, functions for arithmetic operations, handling complex numbers, etc.
Trigonometric Functions:
NumPy has standard trigonometric functions which return trigonometric ratios for a given angle in radians.
np.sin()
np.cos()
np.tan()
arcsin, arcos, and arctan functions return the trigonometric inverse of sin, cos, and tan of the given angle.
The result of these functions can be verified by numpy.degrees() function by converting radians to degrees.
In [3]:
print(np.sin(0))
a = np.array([0,30,45,60,90])
print ('Sine of different angles:')
# Convert to radians by multiplying with pi/180
print (np.sin(a*np.pi/180))
print ('Cosine values for angles in array:')
print (np.cos(a*np.pi/180) )
print ('Tangent values for given angles:')
print (np.tan(a*np.pi/180))
In [4]:
#inverse tri
a = np.array([0,30,45,60,90])
#print 'Array containing sine values:'
sin = np.sin(a*np.pi/180)
print( sin )
print ('\n')
print ('Compute sine inverse of angles. Returned values are in radians.')
inv = np.arcsin(sin)
print (inv )
print ('\n')
print( 'Check result by converting to degrees:' )
print (np.degrees(inv))
print ('\n')
print ('arccos and arctan functions behave similarly:' )
cos = np.cos(a*np.pi/180)
print (cos)
print ('\n')
print ('Inverse of cos:')
inv = np.arccos(cos)
print (inv)
print ('\n')
print ('In degrees:')
print (np.degrees(inv))
print ('\n')
print ('Tan function:' )
tan = np.tan(a*np.pi/180)
print (tan)
print ('Inverse of tan:')
inv = np.arctan(tan)
print (inv)
print ('\n')
print ('In degrees:' )
print (np.degrees(inv))
numpy.around()
This is a function that returns the value rounded to the desired precision. The function takes the following parameters.
syntax : numpy.around(a,decimals)
In [8]:
#round off
a = np.array([1.0,5.55, 123, 0.567, 25.532])
print ('Original array:')
print (a )
print ('\n')
print ('After rounding:')
print (np.around(a))
print (np.around(a, decimals = 1))
numpy.floor()
This function returns the largest integer not greater than the input parameter. The floor of the scalar x is the largest integer i, such that i <= x. Note that in Python, flooring always is rounded away from 0.
In [9]:
a = np.array([-1.7, 1.5, -0.2, 0.6, 10])
print ('array:')
print (a)
print ('\n')
print ('The modified array:')
#returns largest intgres
print (np.floor(a))
#returns lowest intgers
print (np.ceil(a))
Basic operations:
Input arrays for performing arithmetic operations such as add(), subtract(), multiply(), and divide() must be either of the same shape or should conform to array broadcasting rules.
Use +, -, *, / and ** to perform element wise addition, subtraction, multiplication, division and power.
In [10]:
x=np.array([1,2,3])
y=np.array([4,5,6])
print(x + y) # elementwise addition [1 2 3] + [4 5 6] = [5 7 9]
print('\n')
print(x - y) # elementwise subtraction [1 2 3] - [4 5 6] = [-3 -3 -3]
In [11]:
print(x * y) # elementwise multiplication [1 2 3] * [4 5 6] = [4 10 18]
print(x / y) # elementwise divison [1 2 3] / [4 5 6] = [0.25 0.4 0.5]
print(x**2) # elementwise power [1 2 3] ^2 = [1 4 9]
In [12]:
a = np.arange(9, dtype = np.float).reshape(3,3)
print ('First array:')
print (a )
print ('Second array:' )
b = np.array([10,10,10])
print (b )
print ('\n')
print ('Add the two arrays:')
print (np.add(a,b))
print ('\n')
print ('Subtract the two arrays:')
print (np.subtract(a,b))
print ('\n')
print ('Multiply the two arrays:')
print (np.multiply(a,b))
print ('Divide the two arrays:')
print (np.divide(a,b))
Statistical Functions:
NumPy has quite a few useful statistical functions for finding minimum, maximum, percentile standard deviation and variance, etc. from the given elements in the array.
In [13]:
a = np.array([-4, -2, 1, 3, 5])
a.sum()
Out[13]:
In [14]:
a.max()
Out[14]:
In [15]:
a.min()
Out[15]:
In [16]:
np.average(a)
Out[16]:
In [17]:
a.mean()
Out[17]:
In [18]:
a.std() #Standard deviation is the square root of the average of squared deviations from mean
Out[18]:
Variance is the average of squared deviations, i.e., mean(abs(x - x.mean())**2). In other words, the standard deviation is the square root of variance.
In [19]:
np.var([1,2,3,4])
Out[19]:
In [20]:
a.argmax()
Out[20]:
In [21]:
a.argmin()
Out[21]:
No Copy:
Simple assignments do not make the copy of array object. Instead, it uses the same id() of the original array to access it. The id() returns a universal identifier of Python object, similar to the pointer in C.
View or Shallow Copy:
NumPy has ndarray.view() method which is a new array object that looks at the same data of the original array.
Deep copy:
The ndarray.copy() function creates a deep copy. It is a complete copy of the array and its data, and doesn’t share with the original array.
In [22]:
#no copy
a = np.arange(6)
print ('Our array is:' )
print (a )
print ('Applying id() function:')
print (id(a))
print ('a is assigned to b:' )
b = a
print (b)
print ('b has same id():')
print (id(b))
print ('Change shape of b:')
b.shape = 3,2
print (b)
print ('Shape of a also gets changed:')
print (a)
In [23]:
#view
a = np.array([1,2,3,4])
#print 'Array a:'
print (a )
print(id(a))
#Create view of a:
b = a.view()
print( b )
b.shape=(2,2)
print(id(b))
print (b is a)
print(b.shape)
print(a.shape)
In [24]:
#copy
a = np.array([[10,10], [2,3], [4,5]])
print ('Array a is:')
print( a)
# 'Create a deep copy of a:'
b = a.copy()
print ('Array b is:')
print (b)
#b does not share any memory of a
print ('Can we write b is a')
print (b is a)
In [25]:
#normal example
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])
print(a.shape)
print(b.shape)
c = a * b
print (c)
In [26]:
#Broadcasting
x = np.arange(4)
y = np.ones(5)
xb=x.reshape(4,1)
print(xb)
#bd
print(xb + y)
(xb + y).shape
Out[26]:
Note : 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.
In [27]:
#Matrix operations
z = np.array([y, y**2])
print(len(z)) # number of rows of array
Let's look at transposing arrays. Transposing permutes the dimensions of the array.
In [28]:
y=np.arange(5)
z = np.array([y, y ** 2])
z
Out[28]:
In [29]:
#The shape of array z is (2,3) before transposing.
z.shape
Out[29]:
In [30]:
z.T
Out[30]:
Dot Product:
[x1,x2,x2]clo[y1,y2,y3] = x1y1+x2xy2+x3y3
In [31]:
x=np.array([1,2,3])
y=np.array([4,5,6])
x.dot(y) # dot product 1*4 + 2*5 + 3*6
Out[31]:
In [33]:
tp = np.random.randint(0, 10, (4,3))
tp
Out[33]:
In [34]:
#Iterate by row:
for row in tp:
print(row)
In [35]:
#Iterate by index:
for i, row in enumerate(tp):
print('row', i, 'is', row)
In [36]:
#Use zip to iterate over multiple iterables.
tp2=tp*2
tp2
Out[36]:
In [37]:
for i, j in zip(tp, tp2):
print(i,'+',j,'=',i+j)
NumPy package contains an iterator object numpy.nditer. It is an efficient multidimensional iterator object using which it is possible to iterate over an array.
In [38]:
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('Original array is:')
print (a)
print ('\n')
print ('Modified array is:')
for x in np.nditer(a):
print (x)
ix_() function:
The ix_ function can be used to combine different vectors so as to obtain the result for each n-tuplet.
In [39]:
a = np.array([2,3,4,5])
b = np.array([8,5,4])
c = np.array([5,4,6,8,3])
ax,bx,cx = np.ix_(a,b,c)
result = ax+bx*cx
result
result[3,2,4]
a[3]+b[2]*c[4]
Out[39]:
In [15]:
#NumPy package contains a Matrix library numpy.matlib.
import numpy.matlib
#matlib.empty()
#numpy.matlib.empty(shape, dtype, order)
print (np.matlib.empty((2,2)))
print('\n')
#ones
print (np.matlib.ones((2,2)))
print('\n')
#random
print (np.matlib.rand(3,3))
print('\n')
#This function returns the matrix filled with zeros.
#numpy.matlib.zeros()
print (np.matlib.zeros((2,2)))
print('\n')
#numpy.matlib.eye()
#This function returns a matrix with 1 along the diagonal elements and the zeros elsewhere. The function takes the following parameters.
#numpy.matlib.eye(n, M,k, dtype)
print (np.matlib.eye(n = 3, M = 3, k = 1, dtype = float))
print('\n')
#numpy.matlib.identity()
#The numpy.matlib.identity() function returns the Identity matrix of the given size.
#An identity matrix is a square matrix with all diagonal elements as 1.
np.matlib.identity(3)
Out[15]:
In [18]:
#creation matrix
i = np.matrix('1,2,3,4')
print(i)
#array to matrix
list=[1,2,3,4]
k = np.asmatrix (list)
print(k)
print(type(k))
NumPy package contains numpy.linalg module that provides all the functionality required for linear algebra
In [19]:
#det
b = np.array([[6,1,1], [4, -2, 5], [2,8,7]])
print (b)
print('\n')
print (np.linalg.det(b))
print('\n')
print (6*(-2*7 - 5*8) - 1*(4*7 - 5*2) + 1*(4*8 - -2*2))
In [20]:
#dot
#Dot product of the two arrays
#vdot
#Dot product of the two vectors
#linear
dou = np.array([[1,2],[3,4]])
bou = np.array([[11,12],[13,14]])
print(np.dot(dou,bou)) #[[1*11+2*13, 1*12+2*14],[3*11+4*13, 3*12+4*14]]
print('\n')
print(np.vdot(dou,bou)) #1*11 + 2*12 + 3*13 + 4*14
In [21]:
#Solve the system of equations 3 * x0 + x1 = 9 and x0 + 2 * x1 = 8:
al = np.array([[3,1], [1,2]])
bl = np.array([9,8])
x = np.linalg.solve(al, bl)
print(x)
In [22]:
a = np.array([[1,1,1],[0,2,5],[2,5,-1]])
#'Array a
print (a)
print('\n')
ainv = np.linalg.inv(a)
print(ainv)
Using Matplotlib with numpy
In [23]:
from matplotlib import pyplot as plt
x = np.arange(1,11)
y = 2 * x + 5
plt.title("Matplotlib demo")
plt.xlabel("x axis caption")
plt.ylabel("y axis caption")
plt.plot(x,y)
plt.show()
In [24]:
N = 8
y = np.zeros(N)
y
Out[24]:
In [28]:
x1 = np.linspace(0, 10, N, endpoint=True)
In [29]:
x2 = np.linspace(0, 10, N, endpoint=False)
In [30]:
plt.plot(x1, y, 'o')
plt.plot(x2, y + 0.5, 'o')
Out[30]:
In [31]:
plt.ylim([-0.5, 1])
plt.show()
In [33]:
import time
import numpy as np
size_of_vec = 100000
def pure_python_version():
t1 = time.time()
X = range(size_of_vec)
Y = range(size_of_vec)
Z = []
for i in range(len(X)):
Z.append(X[i] + Y[i])
return time.time() - t1
def numpy_version():
t1 = time.time()
X = np.arange(size_of_vec)
Y = np.arange(size_of_vec)
Z = X + Y
return time.time() - t1
t1 = pure_python_version()
t2 = numpy_version()
print(t1, t2)
#print("this example Numpy is " + str(t1/t2) + " faster!")