Workshop Notes-2 Handling Array with NumPy
January 27, 2025
1 Introduction
• Python comes with a data structure, such as List, for array operations
• A Python list on its own is not suitable to perform heavy mathematical operations.
• NumPy is a wonderful Python package produced by Travis Oliphant, which has been created
fundamentally for scientific computing.
• It helps handle large multidimensional arrays and matrices, along with a large library of
high-level mathematical functions to operate on these arrays.
• A NumPy array would require much less memory to store the same amount of data compared
to a Python list, which helps in reading and writing from the array in a faster manner.
2 Creating an array
[1]: import numpy as np
list1 = [1, 2, 3, 4, 5, 6]
a1 = np.array(list1)
[2]: print(a1)
[1 2 3 4 5 6]
[3]: print(type(a1))
<class 'numpy.ndarray'>
[4]: print(a1.ndim)
[5]: print(a1.dtype)
int32
[6]: print(a1.shape)
(6,)
[7]: print(sum(a1))
1
21
[8]: print(a1.sum())
21
[9]: a1.mean()
[9]: 3.5
[10]: a1.min()
[10]: 1
[11]: a1.max()
[11]: 6
[12]: np.std(a1)
[12]: 1.707825127659933
[13]: print(a1==2)
[False True False False False False]
[14]: print(sum(a1==2))
[15]: print(a1**2)
[ 1 4 9 16 25 36]
[16]: print(a1.prod())
720
[17]: print(np.prod(a1))
720
[18]: print(np.cos(a1))
[ 0.54030231 -0.41614684 -0.9899925 -0.65364362 0.28366219 0.96017029]
[19]: list2 = [10, 9, 8, 7, 6, 5]
a2 = np.array(list2)
a3 = a1 + a2
print(a3)
[11 11 11 11 11 11]
2
[20]: print(a1-a2)
[-9 -7 -5 -3 -1 1]
[21]: print(a1*a2)
[10 18 24 28 30 30]
[22]: print(sum(a1*a2))
140
[23]: print(np.sum(a1*a2))
140
[24]: a3=np.repeat(1,10)
print(a3)
[1 1 1 1 1 1 1 1 1 1]
[25]: a4=np.repeat([1,2,3],[3,2,1])
print(a4)
[1 1 1 2 2 3]
3 Array in higher dimension
[22]: a2 = np.array([['a','b'],['c','d']]) ## 2d
[23]: print(a2)
[['a' 'b']
['c' 'd']]
[24]: print(a2.ndim)
[26]: print(a2.shape)
(2, 2)
4 Array with random numbers
[42]: r1 = np.random.randint(10) ## one random number b/w 0 to 9
print(r1)
3
[43]: np.random.seed(4)
r1 = np.random.randint(10)
print(r1)
[44]: r1 = np.random.randint(10,100) ## one random number b/w 10 to 99
print(r1)
79
[45]: r1 = np.random.randint(10,100,5) ## 5 random numbers b/w 10 to 99
print(r1)
print(type(r1))
[11 97 82 60 19]
<class 'numpy.ndarray'>
[46]: r1 = np.random.randint(10,100,(5,4)) ## 5 random numbers b/w 10 to 99
print(r1)
[[68 65 65 67]
[46 60 54 48]
[62 13 10 65]
[31 31 83 48]
[66 76 56 40]]
[29]: np.random.seed(2)
r1 = np.random.randint(10,100,(2,3,2)) ## 5 random numbers b/w 10 to 99
print(r1)
[[[50 25]
[82 32]
[53 92]]
[[85 17]
[44 59]
[85 95]]]
[48]: rng = np.random.default_rng(1)
s=rng.binomial(10, 0.4,10)
print(s)
[4 7 2 7 3 4 5 4 4 1]
[49]: rng = np.random.default_rng(1)
s=rng.poisson(1, 10)
print(s)
[2 1 1 1 0 2 1 1 1 0]
4
[50]: np.random.geometric(0.5,[4,4])
[50]: array([[1, 1, 1, 1],
[2, 1, 2, 1],
[3, 2, 1, 2],
[5, 2, 4, 1]])
[51]: rng = np.random.default_rng(1)
s=rng.negative_binomial(10, 0.4,10)
print(s)
[14 13 13 8 14 22 16 9 11 14]
[52]: r1 = np.random.uniform(0,1,(5,4)) ## 5 random numbers b/w 0 to 1
print(r1)
[[0.56714413 0.42754596 0.43674726 0.77655918]
[0.53560417 0.95374223 0.54420816 0.08209492]
[0.3663424 0.8508505 0.40627504 0.02720237]
[0.24717724 0.06714437 0.99385201 0.97058031]
[0.80025835 0.60181712 0.76495986 0.16922545]]
[53]: r1 = np.random.uniform(10,100,(5,4)) ## 20 random numbers b/w 10 to 99
r1 = np.round(r1,3)
print(r1)
[[36.372 57.166 42.096 14.111]
[98.484 49.722 55.36 39.119]
[33.377 44.82 84.882 76.307]
[44.129 11.172 81.766 34.245]
[62.442 12.3 69.598 44.877]]
[54]: np.random.exponential(0.5,[4,4])
[54]: array([[0.34365592, 0.26799124, 0.2160626 , 0.40034159],
[1.80430804, 0.05982902, 0.18789869, 0.02134818],
[0.67046887, 0.5357599 , 0.12080383, 0.26957263],
[0.51619032, 0.54158801, 0.0934523 , 1.06706392]])
[55]: mean, sigma = 0, 1
rng = np.random.default_rng(1)
s=rng.normal(mean, sigma, 10)
print(s)
[ 0.34558419 0.82161814 0.33043708 -1.30315723 0.90535587 0.44637457
-0.53695324 0.5811181 0.3645724 0.2941325 ]
[56]: shape, scale = 2., 2. # mean=4, std=2*sqrt(2)
rng = np.random.default_rng(1)
s = rng.gamma(shape, scale, 10)
5
print(s)
[4.30761495 4.26138082 6.25997772 2.13025573 4.36604421 3.40725911
1.77047536 2.23703606 3.43695087 1.69461262]
[57]: np.random.chisquare(1,[4,3])
[57]: array([[1.64161306, 2.73493317, 1.82260612],
[0.09753877, 0.72426419, 0.13915823],
[0.35235571, 0.77435882, 0.82414554],
[0.721828 , 0.60579436, 0.12084626]])
[58]: mean, sigma = 0, 1
rng = np.random.default_rng(1)
s=rng.lognormal(mean, sigma, 10)
print(s)
[1.41281503 2.27417681 1.39157622 0.2716727 2.47281176 1.56263668
0.58452646 1.78803652 1.43989817 1.3419617 ]
5 Array indexing and slicing
[59]: np.random.seed(10)
r1 = np.random.randint(1,20,(5,4))
print(r1)
[[10 5 16 1]
[18 17 18 9]
[10 1 11 9]
[ 5 17 5 16]
[12 12 2 9]]
[60]: print(len(r1))
[61]: print(r1[2])
[10 1 11 9]
[62]: print(r1[-2])
[ 5 17 5 16]
[63]: print(r1[0,3])
[64]: print(r1[0][3])
6
[65]: print(r1[:])
[[10 5 16 1]
[18 17 18 9]
[10 1 11 9]
[ 5 17 5 16]
[12 12 2 9]]
[66]: print(r1[1:4,0:3])
[[18 17 18]
[10 1 11]
[ 5 17 5]]
[67]: print(r1[0:5:2,1:5:2]) ## row:column:step
[[ 5 1]
[ 1 9]
[12 9]]
[68]: print(np.max(r1))
print(np.max(r1,axis=0)) ## column wise
print(np.max(r1,axis=1)) ## row wise
18
[18 17 18 16]
[16 18 11 17 12]
[69]: print(np.min(r1))
print(np.min(r1,axis=0)) ## column wise
print(np.min(r1,axis=1)) ## row wise
1
[5 1 2 1]
[1 9 1 5 2]
[70]: print(np.argmax(r1)) ## index of max number
print(np.argmax(r1,axis=0)) ## column wise
print(np.argmax(r1,axis=1)) ## row wise
4
[1 1 1 3]
[2 0 2 1 0]
[71]: print(np.argmin(r1)) ## index of min number
print(np.argmin(r1,axis=0)) ## column wise
print(np.argmin(r1,axis=1)) ## row wise
3
[3 2 4 0]
[3 3 1 0 2]
7
[72]: print(np.sum(r1))
print(np.sum(r1,axis=0)) ## column wise
print(np.sum(r1,axis=1)) ## row wise
203
[55 52 52 44]
[32 62 31 43 35]
[73]: print(np.mean(r1))
print(np.mean(r1,axis=0)) ## column wise
print(np.mean(r1,axis=1)) ## row wise
10.15
[11. 10.4 10.4 8.8]
[ 8. 15.5 7.75 10.75 8.75]
6 Shape Manupulation
[74]: print(r1)
r2=r1.reshape(20)
print(r2)
[[10 5 16 1]
[18 17 18 9]
[10 1 11 9]
[ 5 17 5 16]
[12 12 2 9]]
[10 5 16 1 18 17 18 9 10 1 11 9 5 17 5 16 12 12 2 9]
[75]: r1.shape = (4,5)
print(r1)
[[10 5 16 1 18]
[17 18 9 10 1]
[11 9 5 17 5]
[16 12 12 2 9]]
[76]: r3 = r1.reshape((2,2,5))
print(r3)
[[[10 5 16 1 18]
[17 18 9 10 1]]
[[11 9 5 17 5]
[16 12 12 2 9]]]
[77]: r4 = r1.astype('str')
print(r4)
8
[['10' '5' '16' '1' '18']
['17' '18' '9' '10' '1']
['11' '9' '5' '17' '5']
['16' '12' '12' '2' '9']]
[78]: r5 = r1.astype('float')
print(r5)
[[10. 5. 16. 1. 18.]
[17. 18. 9. 10. 1.]
[11. 9. 5. 17. 5.]
[16. 12. 12. 2. 9.]]
7 Sequence
[31]: s1 = np.arange(1, 9, 1)
print("\n A sequential array with a step 1: \n",s1)
A sequential array with a step 1:
[1 2 3 4 5 6 7 8]
[32]: # Create a sequence of integers from 10 to 1 with a step of -2
s2 = np.arange(10, 1, -2)
print("\n A sequential array with a negative step: \n",s2)
A sequential array with a negative step:
[10 8 6 4 2]
[33]: s3=range(1,10,1)
print(type(s3))
s4=np.array(s3)
print(s4)
<class 'range'>
[1 2 3 4 5 6 7 8 9]
[82]: # To find a sub-array when indices are given
s5 = s4[np.array([3, 0, 2])]
print("\n Elements at specified indices are:\n",s5)
Elements at specified indices are:
[4 1 3]
[83]: x=np.r_[1:50:3]
print(x)
print(type(x))
9
[ 1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49]
<class 'numpy.ndarray'>
[84]: print(x==10)
print(sum(x==10))
[False False False True False False False False False False False False
False False False False False]
1
[85]: print(np.r_[2,4,1:30:3])
[ 2 4 1 4 7 10 13 16 19 22 25 28]
[86]: print(np.c_[1:20:3])
[[ 1]
[ 4]
[ 7]
[10]
[13]
[16]
[19]]
[34]: x=np.linspace(0, 2, 11)
print(x)
[0. 0.2 0.4 0.6 0.8 1. 1.2 1.4 1.6 1.8 2. ]
8 Matrix Operations
[88]: A1 = np.array([[1, 1],
[0, 1]])
print(A1)
[[1 1]
[0 1]]
[89]: A2 = np.array([[2, 0],
[3, 4]])
print(A2)
[[2 0]
[3 4]]
Product of two matrices
[90]: A1 * A2
10
[90]: array([[2, 0],
[0, 4]])
The above command will perform the element-by-element multiplication. Matrix product can be
performed by the following code:
[91]: np.dot(A1, A2)
[91]: array([[5, 4],
[3, 4]])
power of a matrix
[92]: np.linalg.matrix_power(A1, 2)
[92]: array([[1, 2],
[0, 1]])
Transpose of a Matrix
[93]: print(A1.transpose())
[[1 0]
[1 1]]
[94]: np.transpose(A1)
[94]: array([[1, 0],
[1, 1]])
Diagonal of matrix
[95]: print(np.diag(A1))
print(np.diagonal(A1)) # Alternate
[1 1]
[1 1]
[96]: x=[1,2,3]
A3=np.diag(x)
print(A3)
[[1 0 0]
[0 2 0]
[0 0 3]]
Trace of a matrix
[97]: print(np.trace(A1))
11
Determinant of a matrix
[98]: print(np.linalg.det(A1))
1.0
Inverse of a matrix
[99]: print(np.linalg.inv(A1))
[[ 1. -1.]
[ 0. 1.]]
Zero matrix
[100]: zeros=np.zeros((5,4))
print(zeros)
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
Matrix with 1
[101]: ones=np.ones((5,6))
print(ones)
[[1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1.]]
[102]: ones_int=np.ones((5,6),np.int64)
print(ones_int)
[[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]]
Identity matrix
[103]: identity=np.identity(5)
print(identity)
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
12
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
[104]: identity=np.identity(5,np.int32)
print(identity)
[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]
Eigenvalues and Eigenvectors
[105]: np.linalg.eig(A1)
[105]: (array([1., 1.]),
array([[ 1.00000000e+00, -1.00000000e+00],
[ 0.00000000e+00, 2.22044605e-16]]))
Solve the following system of linear equations:
2x+3y+4z=13
3x+y+2z=8
x+2y+z=5
[9]: A=np.array([[2,3,4],
[3,1,2],
[1,2,1]])
print(A)
b=np.array([13,8,5])
[[2 3 4]
[3 1 2]
[1 2 1]]
[6]: np.linalg.det(A)
[6]: 11.000000000000002
[8]: A1=np.linalg.inv(A)
print(A1)
[[-0.27272727 0.45454545 0.18181818]
[-0.09090909 -0.18181818 0.72727273]
[ 0.45454545 -0.09090909 -0.63636364]]
[11]: sol=np.dot(A1,b)
print(sol)
[1. 1. 2.]
13