Getting Started with Numpy

  • NumPy is the fundamental package for scientific computing in Python.
  • NumPy’s main object is the homogeneous multidimensional array.
  • It is a table of elements (usually numbers), all of the same type, indexed by a tuple of positive integers.
  • In NumPy dimensions are called axes.
  • NumPy’s array class is called ndarray.
  • Numpy means Numerical Python
  • Use PIP, to install numpy from windows command prompt – pip install numpy

Creating Numpy Array

  • ndarray.ndim – the number of axes (dimensions) of the array
  • For a matrix with n rows and m columns, ndarray.shape will be (n,m)
  • ndarray.size – the total number of elements of the array
  • ndarray.dtype – an object describing the type of the elements in the array
  • ndarray.itemsize – the size in bytes of each element of the array. For example, an array of elements of type float64 has itemsize 8 (=64/8), while one of type complex32 has itemsize 4 (=32/8)
>>> import numpy as np
>>> myList = [1,2,3]
>>> narray = np.array(myList)
>>> narray
array([1, 2, 3])
>>> print(narray)
[1 2 3]
>>> narray.dtype
dtype('int32')
>>> narray.shape
(3,)
>>> narray.ndim
1
>>> narray.itemsize
4
>>> narray.size
3
>>> type(narray)
<class 'numpy.ndarray'>
>>> narray.data
<memory at 0x06F3BF38>
  • numpy.arange() – To create sequences of numbers that returns arrays instead of lists
  • numpy.reshape(array, shape, order = ‘C’) – shapes an array without changing data of array.
>>> import numpy as np
>>> narray = np.array([[1,2,3],[4,5,6]])
>>> narray
array([[1, 2, 3],
       [4, 5, 6]])
>>> type(narray)
<class 'numpy.ndarray'>

>>> narrayc = np.array([ [1,2],[3,4] ], dtype=complex)
>>> narrayc
array([[1.+0.j, 2.+0.j],
       [3.+0.j, 4.+0.j]])
>>> type(narrayc)
<class 'numpy.ndarray'>

>>> narrayd = np.arange(5)
>>> print(narrayd)
[0 1 2 3 4]


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

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

>>> narrayd1 = np.arange(8).reshape(2,2,2)
>>> narrayd1
array([[[0, 1],
        [2, 3]],

       [[4, 5],
        [6, 7]]])
>>> narrayd1.shape
(2, 2, 2)
>>>
  • numpy.zeros() – the function zeros creates an array full of zeros
  • numpy.ones() – the function ones creates an array full of ones
  • numpy.empty() – the function empty creates an array whose initial content is random and depends on the state of the memory
  • numpy.full() – creates the constant array
  • numpy.eye() – creates identity matrix
>>> np.zeros((3,4))
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])
>>> np.zeros((1,2))
array([[0., 0.]])
>>> np.zeros((2,2))
array([[0., 0.],
       [0., 0.]])
>>> np.zeros([4,3])
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

>>> np.ones((1,1),dtype=np.int16)
array([[1]], dtype=int16)
>>> np.ones((1,2),dtype=np.int16)
array([[1, 1]], dtype=int16)
>>> np.ones((1,3),dtype=np.int16)
array([[1, 1, 1]], dtype=int16)
>>> np.ones((2,3),dtype=np.int16)
array([[1, 1, 1],
       [1, 1, 1]], dtype=int16)
>>> np.ones((3,3),dtype=np.int16)
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]], dtype=int16)
>>> np.ones((3,2),dtype=np.int16)
array([[1, 1],
       [1, 1],
       [1, 1]], dtype=int16)

>>> np.empty((1,2))
array([[0., 0.]])
>>> np.empty((3,3))
array([[ 0.00000000e+000,  0.00000000e+000,  0.00000000e+000],
       [ 0.00000000e+000,  0.00000000e+000,  0.00000000e+000],
       [ 0.00000000e+000,  0.00000000e+000, -1.32815717e-310]])
>>> np.empty((3,2))
array([[0.00000000e+000, 0.00000000e+000],
       [8.48406935e+175, 7.46514969e+250],
       [8.82813173e+199, 2.64935866e+180]])
>>> np.empty((2,2))
array([[8.48406935e+175, 7.46514969e+250],
       [8.82813173e+199, 2.64935866e+180]])
>>> np.empty((2,1))
array([[0.],
       [0.]])
>>> np.empty((2,5))
array([[6.30452443e-303, 7.17100082e-299, 7.17100082e-299,
        7.17100082e-299, 7.17100082e-299],
       [7.17100082e-299, 7.17218563e-299, 7.17220386e-299,
        4.69958710e-294, 1.16370568e-315]])

>>> a = np.full((2,2),8)
>>> a
array([[8, 8],
       [8, 8]])
>>> a = np.full((3,3),8)
>>> a
array([[8, 8, 8],
       [8, 8, 8],
       [8, 8, 8]])
>>> a = np.full((3,4),8)
>>> a
array([[8, 8, 8, 8],
       [8, 8, 8, 8],
       [8, 8, 8, 8]])
>>>
>>> c = np.eye(2)
>>> c
array([[1., 0.],
       [0., 1.]])
>>> c = np.eye(3)
>>> c
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
  • numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0) – Return evenly spaced numbers over a specified interval. Default number is 50.
>>> np.linspace(0,2,9)
array([0.  , 0.25, 0.5 , 0.75, 1.  , 1.25, 1.5 , 1.75, 2.  ])

>>> np.linspace(5,10,5)
array([ 5.  ,  6.25,  7.5 ,  8.75, 10.  ])

>>> np.linspace(10,100,10)
array([ 10.,  20.,  30.,  40.,  50.,  60.,  70.,  80.,  90., 100.])

>>> np.linspace(10,100)
array([ 10.        ,  11.83673469,  13.67346939,  15.51020408,
        17.34693878,  19.18367347,  21.02040816,  22.85714286,
        24.69387755,  26.53061224,  28.36734694,  30.20408163,
        32.04081633,  33.87755102,  35.71428571,  37.55102041,
        39.3877551 ,  41.2244898 ,  43.06122449,  44.89795918,
        46.73469388,  48.57142857,  50.40816327,  52.24489796,
        54.08163265,  55.91836735,  57.75510204,  59.59183673,
        61.42857143,  63.26530612,  65.10204082,  66.93877551,
        68.7755102 ,  70.6122449 ,  72.44897959,  74.28571429,
        76.12244898,  77.95918367,  79.79591837,  81.63265306,
        83.46938776,  85.30612245,  87.14285714,  88.97959184,
        90.81632653,  92.65306122,  94.48979592,  96.32653061,
        98.16326531, 100.        ])

Some basic operations

  • numpy.random.rand() – Random values in a given shape
  • numpy.random.random() – Return random floats in the half-open interval [0.0, 1.0)
  • numpy.random.randint() – Return random integers from low (inclusive) to high (exclusive)
>>> a = np.array([1,2,3,4,5])
>>> a
array([1, 2, 3, 4, 5])
>>> b = np.arange(4)
>>> b
array([0, 1, 2, 3])
>>> b = np.arange(5)
>>> b
array([0, 1, 2, 3, 4])
>>> c = a + b
>>> c
array([1, 3, 5, 7, 9])
>>> d = a - b
>>> d
array([1, 1, 1, 1, 1])
>>> e = a * b
>>> e
array([ 0,  2,  6, 12, 20])
>>> b**2
array([ 0,  1,  4,  9, 16], dtype=int32)
>>> 10*np.sin(a)
array([ 8.41470985,  9.09297427,  1.41120008, -7.56802495, -9.58924275])
>>> a<10
array([ True,  True,  True,  True,  True])
>>> a<2
array([ True, False, False, False, False])
>>>
>>> A = np.array([ [1,2],[3,4] ])
>>> B = np.array([ [5,6],[7,8] ])
>>> A * B    # Elementary Product
array([[ 5, 12],
       [21, 32]])
>>> A @ B   # Matrix Product
array([[19, 22],
       [43, 50]])
>>> A.dot(B)   # Matrix Product
array([[19, 22],
       [43, 50]])
>>> a = np.ones((2,3),dtype=int)
>>> a
array([[1, 1, 1],
       [1, 1, 1]])
>>> b = np.random.random((2,3))
>>> b
array([[0.96627373, 0.63345685, 0.97194617],
       [0.38913042, 0.53184503, 0.11587659]])
>>> a *= 3
>>> a
array([[3, 3, 3],
       [3, 3, 3]])
>>> b += a
>>> b
array([[3.96627373, 3.63345685, 3.97194617],
       [3.38913042, 3.53184503, 3.11587659]])
>>> b += a
>>> b
array([[6.96627373, 6.63345685, 6.97194617],
       [6.38913042, 6.53184503, 6.11587659]])
>>> c = np.random.random((2,3))
>>> c
array([[0.08325765, 0.21577319, 0.08798369],
       [0.82428389, 0.83826481, 0.85641444]])
>>> a
array([[3, 3, 3],
       [3, 3, 3]])
>>> c += a
>>> c
array([[3.08325765, 3.21577319, 3.08798369],
       [3.82428389, 3.83826481, 3.85641444]])
>>> c
array([[3.08325765, 3.21577319, 3.08798369],
       [3.82428389, 3.83826481, 3.85641444]])
>>> d = np.random.random((2,3))
>>> d
array([[0.27000047, 0.11850203, 0.85250893],
       [0.30778738, 0.75352582, 0.38372075]])
>>> a += d
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int32') with casting rule 'same_kind'


>>> a.dtype.name
'int32'
>>> b.dtype.name
'float64'
>>> c.dtype.name
'float64'
>>>
>>> a = np.random.random((2,3))
>>> a
array([[0.4691446 , 0.65657747, 0.58647271],
       [0.78006868, 0.50436539, 0.45898046]])
>>> a.sum()
3.4556093072004748
>>> a.min()
0.45898045705729573
>>> a.max()
0.7800686828380398
>>>
>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> b = np.arange(11).reshape(3,4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot reshape array of size 11 into shape (3,4)
>>> b.sum(axis=0)
array([12, 15, 18, 21])
>>> b.sum(axis=1)
array([ 6, 22, 38])

>>> A = np.arange(3)
>>> A
array([0, 1, 2])
>>> np.exp(A)
array([1.        , 2.71828183, 7.3890561 ])
>>> np.sqrt(A)
array([0.        , 1.        , 1.41421356])


>>> np.random.random(3)
array([0.86752163, 0.62968186, 0.34211454])
>>> np.random.rand(2,2)
array([[0.13014958, 0.66780134],
       [0.90125996, 0.50430727]])
>>> np.random.rand(3)
array([0.33349714, 0.90846563, 0.91433236])
>>> np.random.randint(2,10,(3,2),dtype=int)
array([[5, 8],
       [3, 4],
       [7, 2]])

>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> b = np.arange(6,11)
>>> b
array([ 6,  7,  8,  9, 10])
>>> np.concatenate((a,b))
array([ 0,  1,  2,  3,  4,  6,  7,  8,  9, 10])

Indexing, Slicing and Iterating

>>> a = np.arange(5)**2
>>> a
array([ 0,  1,  4,  9, 16], dtype=int32)
>>> a[2]
4
>>> a[2:3]
array([4], dtype=int32)
>>> a[:5:2]
array([ 0,  4, 16], dtype=int32)
>>> a[:4:2]
array([0, 4], dtype=int32)
>>> a
array([ 0,  1,  4,  9, 16], dtype=int32)

>>> a[ : : -1]
array([16,  9,  4,  1,  0], dtype=int32)
>>> a
array([ 0,  1,  4,  9, 16], dtype=int32)

>>> for i in a:
...     print(i)
...
0
1
4
9
16
>>>
>>> def fun(x,y):
...     return 5*x+y
...
>>> b = np.fromfunction(fun,(5,4),dtype=int)
>>> b
array([[ 0,  1,  2,  3],
       [ 5,  6,  7,  8],
       [10, 11, 12, 13],
       [15, 16, 17, 18],
       [20, 21, 22, 23]])
>>> b[2,3]
13
>>> b[1,1]
6
>>> b[0,0]
0
>>> b[0.1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
>>> b[0,1]
1
>>> b[4,4]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: index 4 is out of bounds for axis 1 with size 4
>>> b[4,3]
23
>>> b[-1]
array([20, 21, 22, 23])
>>> b[1]
array([5, 6, 7, 8])
>>> b[0]
array([0, 1, 2, 3])
>>> b[:1]
array([[0, 1, 2, 3]])
>>> b[-3]
array([10, 11, 12, 13])
>>> b
array([[ 0,  1,  2,  3],
       [ 5,  6,  7,  8],
       [10, 11, 12, 13],
       [15, 16, 17, 18],
       [20, 21, 22, 23]])
>>> for row in b:
...     print(row)
...
[0 1 2 3]
[5 6 7 8]
[10 11 12 13]
[15 16 17 18]
[20 21 22 23]
>>> for e in b.flat:
...     print(e)
...
0
1
2
3
5
6
7
8
10
11
12
13
15
16
17
18
20
21
22
23
>>> b
array([[ 0,  1,  2,  3],
       [ 5,  6,  7,  8],
       [10, 11, 12, 13],
       [15, 16, 17, 18],
       [20, 21, 22, 23]])
>>> #each row in the 2nd column of b
...
>>> b[0:5,1]
array([ 1,  6, 11, 16, 21])
>>> b[ : ,1]
array([ 1,  6, 11, 16, 21])
>>> b[1:3, :] # each column in the 2nd and 3rd row of b
array([[ 5,  6,  7,  8],
       [10, 11, 12, 13]])

Shape Manipulation

  • reshape() – give a new shape to an array without changing its data. Use
  • ravel() – return a contiguous flattened array.
  • resize() – change shape and size of array in place.
  • transpose() – return a view of the array with axes transposed. T
  • T – Attribute T also returns transposed array.
  • flatten() – return a copy of the array collapsed into one dimension.
  • numpy.linalg.inv() – matrix inversion
  • numpy.hstack() – stacks array horizontally
  • numpy.vstack() – stacks array vertically
  • numpy.hsplit() – Split an array into multiple sub-arrays horizontally (column-wise)
  • numpy.vsplit() – Split an array into multiple sub-arrays vertically (row-wise).
  • numpy.split() – Split an array into multiple sub-arrays of equal size.
>>> a = np.arange(12)
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a.shape
(3, 4)
>>> a.ravel()
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> a.reshape(6,2)
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6,  7],
       [ 8,  9],
       [10, 11]])
>>> a.T
array([[ 0,  4,  8],
       [ 1,  5,  9],
       [ 2,  6, 10],
       [ 3,  7, 11]])
>>> a.T.shape
(4, 3)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a.resize((2,6))
>>> a
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
>>> a.reshape(3,-1)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> arr = np.arange(5)
>>> arr1 = np.random.random(5)
>>> np.vstack((arr,arr1))
array([[0.        , 1.        , 2.        , 3.        , 4.        ],
       [0.97878686, 0.56190355, 0.12641282, 0.65136447, 0.83568717]])
>>> np.hstack((arr,arr1))
array([0.        , 1.        , 2.        , 3.        , 4.        ,
       0.97878686, 0.56190355, 0.12641282, 0.65136447, 0.83568717])
>>> a = np.array([1,2])
>>> b = np.array([3,4])
>>> np.column_stack((a,b))
array([[1, 3],
       [2, 4]])
>>> np.hstack((a,b))
array([1, 2, 3, 4])

>>> a = np.random.random((2,12))
>>> a
array([[0.08146388, 0.41590075, 0.79196426, 0.14672239, 0.52316042,
        0.11668935, 0.43981522, 0.82527797, 0.58228172, 0.6156643 ,
        0.80267198, 0.05923876],
       [0.26184573, 0.1960858 , 0.74868341, 0.49577455, 0.62185744,
        0.47756788, 0.11381945, 0.00466714, 0.23567282, 0.94185927,
        0.73154317, 0.79143902]])
>>> np.hsplit(a,3)
[array([[0.08146388, 0.41590075, 0.79196426, 0.14672239],
       [0.26184573, 0.1960858 , 0.74868341, 0.49577455]]), array([[0.52316042, 0.11668935, 0.43981522, 0.82527797],
       [0.62185744, 0.47756788, 0.11381945, 0.00466714]]), array([[0.58228172, 0.6156643 , 0.80267198, 0.05923876],
       [0.23567282, 0.94185927, 0.73154317, 0.79143902]])]

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

>>> x = np.arange(9.0)
>>> x
array([0., 1., 2., 3., 4., 5., 6., 7., 8.])
>>> np.split(x,3)
[array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])]

>>> a =np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a.flatten()
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

>>> a = np.arange(4).reshape(2,2)
>>> a
array([[0, 1],
       [2, 3]])
>>> np.linalg.inv(a)
array([[-1.5,  0.5],
       [ 1. ,  0. ]])

Copies and Views

  • No Copy at All – Simple assignments make no copy of array objects or of their data.
  • View or Shallow Copy – Different array objects can share the same data. The view method creates a new array object that looks at the same data.
  • Deep Copy – The copy method makes a complete copy of the array and its data.
# No Copy at all
>>> a = np.arange(6)
>>> b = a
>>> a
array([0, 1, 2, 3, 4, 5])
>>> b
array([0, 1, 2, 3, 4, 5])
>>> b is a
True
>>> b.shape
(6,)

>>> b.shape = 3,2
>>> b
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> a.shape
(3, 2)
>>> a
array([[0, 1],
       [2, 3],
       [4, 5]])

# View or Shallow Copy
>>> a
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> b
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> c = a.view()
>>> c
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> c is a
False
>>> c.flags.owndata
False
>>> c.shape
(3, 2)
>>> c.shape =2,3
>>> c
array([[0, 1, 2],
       [3, 4, 5]])
>>> a
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> c[0:2] = 22
>>> c
array([[22, 22, 22],
       [22, 22, 22]])
>>> a
array([[22, 22],
       [22, 22],
       [22, 22]])

# Deep Copy

>>> a
array([[22, 22],
       [22, 22],
       [22, 22]])
>>> d = a.copy()
>>> d is a
False
>>> d.base is a
False
>>> d[0,0]=222
>>> d
array([[222,  22],
       [ 22,  22],
       [ 22,  22]])
>>> a
array([[22, 22],
       [22, 22],
       [22, 22]])
>>> d[0,0]=86
>>> d
array([[86, 22],
       [22, 22],
       [22, 22]])
>>> a
array([[22, 22],
       [22, 22],
       [22, 22]])

Braodcasting

  • Broadcasting allows universal functions to deal in a meaningful way with inputs that do not have exactly the same shape.
  • The first rule of broadcasting is that if all input arrays do not have the same number of dimensions, a “1” will be repeatedly prepended to the shapes of the smaller arrays until all the arrays have the same number of dimensions.
  • The second rule of broadcasting ensures that arrays with a size of 1 along a particular dimension act as if they had the size of the array with the largest shape along that dimension. The value of the array element is assumed to be the same along that dimension for the “broadcast” array.
>>> a = np.array([1,2,3])
>>> a
array([1, 2, 3])
>>> b = 4
>>> a * b
array([ 4,  8, 12])
>>>
>>> x = np.arange(4)
>>> x
array([0, 1, 2, 3])
>>> z = x.reshape(4,1)
>>> z
array([[0],
       [1],
       [2],
       [3]])
>>> y =np.ones(5)
>>> y
array([1., 1., 1., 1., 1.])
>>> p = np.ones((3,4))
>>> p
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])
>>> x.shape
(4,)
>>> y.shape
(5,)
>>> x + y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (4,) (5,)
>>> z.shape
(4, 1)
>>> y.shape
(5,)
>>> (z+y).shape
(4, 5)
>>> z + y
array([[1., 1., 1., 1., 1.],
       [2., 2., 2., 2., 2.],
       [3., 3., 3., 3., 3.],
       [4., 4., 4., 4., 4.]])
>>> x.shape
(4,)
>>> y.shape
(5,)
>>> z.shape
(4, 1)
>>> p.shape
(3, 4)
>>> (x + p).shape
(3, 4)
>>> x + p
array([[1., 2., 3., 4.],
       [1., 2., 3., 4.],
       [1., 2., 3., 4.]])

References

  • https://docs.scipy.org/doc/numpy/user/quickstart.html

Learn more about Python Data Science Libraries in our upcoming Blog articles.

Happy Learning!