0% found this document useful (0 votes)
4 views

NumPy 2

Intermediate Numpy

Uploaded by

mananbarwal2
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

NumPy 2

Intermediate Numpy

Uploaded by

mananbarwal2
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

NumPy: A Python Library for Scientific

Computing
The basics
In [2]:
import numpy as np

a = np.arange(15).reshape(3, 5) # Creates a 3x5 NumPy array with values in [0, 14]


a

array([[ 0, 1, 2, 3, 4],
Out[2]:
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

In [3]:
squares = np.array([x**2 for x in range(10)])
squares

array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81])


Out[3]:

In [4]:
type(squares)

numpy.ndarray
Out[4]:

Useful n-dimensional array (np.array) methods

In [5]:
a.shape

(3, 5)
Out[5]:

In [6]:
a.ndim

2
Out[6]:

In [7]:
a.dtype.name

'int32'
Out[7]:

In [8]:
a.itemsize

4
Out[8]:

In [9]:
a.size

15
Out[9]:

In [10]:
type(a)

numpy.ndarray
Out[10]:
Creating arrays from Python's sequence types

In [11]:
squares = [x**2 for x in range(10)] # python list
cubes = tuple(x**3 for x in range(10)) # python tuple
evens = {x for x in range(10) if x%2 == 0} # python set

print(type(squares))
print(type(cubes))
print(type(evens))

<class 'list'>
<class 'tuple'>
<class 'set'>

In [12]:
a = np.array(squares)
b = np.array(cubes)
c = np.array(evens)

if type(a) == type(b) == type(c):


print(type(a))

<class 'numpy.ndarray'>

In [13]:
seq2 = [[x, x**2, x**3] for x in range(10)]
seq3 = [[[x for x in range(3)], [y for y in range(3, 6)]] for z in range(10)]

a = np.array(seq2) # create array from nested lists of depth 2


b = np.array(seq3) # create array from nested lists of depth 3

print(a.ndim)
print(b.ndim)

2
3

In [14]:
odds = list(i for i in range(10) if i%2 != 0)

numpy_odds = np.array(odds, dtype=complex) # declare data type during instantiation


numpy_odds

array([1.+0.j, 3.+0.j, 5.+0.j, 7.+0.j, 9.+0.j])


Out[14]:

In [15]:
zeros = np.zeros((3, 3), dtype=np.int32) # create a 3x3 array of 0's
ones = np.ones((2, 2), dtype=np.float64) # create a 2x2 array of 1's
empty = np.empty((3, 3))

print(zeros, zeros.dtype.name)
print(ones, ones.dtype.name)
print(empty, empty.dtype.name)

[[0 0 0]
[0 0 0]
[0 0 0]] int32
[[1. 1.]
[1. 1.]] float64
[[0.00000000e+000 0.00000000e+000 0.00000000e+000]
[0.00000000e+000 0.00000000e+000 8.35959073e-321]
[1.37962117e-306 0.00000000e+000 0.00000000e+000]] float64
In [16]:
a = np.arange(5, 30, 5) # create array from range [5, 30) with step of 5
a

array([ 5, 10, 15, 20, 25])


Out[16]:

In [17]:
b = np.linspace(0, 1, 100) # create array of 100 values between 0 and 1
b

array([0. , 0.01010101, 0.02020202, 0.03030303, 0.04040404,


Out[17]:
0.05050505, 0.06060606, 0.07070707, 0.08080808, 0.09090909,
0.1010101 , 0.11111111, 0.12121212, 0.13131313, 0.14141414,
0.15151515, 0.16161616, 0.17171717, 0.18181818, 0.19191919,
0.2020202 , 0.21212121, 0.22222222, 0.23232323, 0.24242424,
0.25252525, 0.26262626, 0.27272727, 0.28282828, 0.29292929,
0.3030303 , 0.31313131, 0.32323232, 0.33333333, 0.34343434,
0.35353535, 0.36363636, 0.37373737, 0.38383838, 0.39393939,
0.4040404 , 0.41414141, 0.42424242, 0.43434343, 0.44444444,
0.45454545, 0.46464646, 0.47474747, 0.48484848, 0.49494949,
0.50505051, 0.51515152, 0.52525253, 0.53535354, 0.54545455,
0.55555556, 0.56565657, 0.57575758, 0.58585859, 0.5959596 ,
0.60606061, 0.61616162, 0.62626263, 0.63636364, 0.64646465,
0.65656566, 0.66666667, 0.67676768, 0.68686869, 0.6969697 ,
0.70707071, 0.71717172, 0.72727273, 0.73737374, 0.74747475,
0.75757576, 0.76767677, 0.77777778, 0.78787879, 0.7979798 ,
0.80808081, 0.81818182, 0.82828283, 0.83838384, 0.84848485,
0.85858586, 0.86868687, 0.87878788, 0.88888889, 0.8989899 ,
0.90909091, 0.91919192, 0.92929293, 0.93939394, 0.94949495,
0.95959596, 0.96969697, 0.97979798, 0.98989899, 1. ])

In [18]:
from numpy import pi

c = np.linspace(0, 2*pi, 10) # useful for evaluating trigonometric function at point

f = np.sin(c)
f

array([ 0.00000000e+00, 6.42787610e-01, 9.84807753e-01, 8.66025404e-01,


Out[18]:
3.42020143e-01, -3.42020143e-01, -8.66025404e-01, -9.84807753e-01,
-6.42787610e-01, -2.44929360e-16])

In [19]:
# creating an array from a function

def f(row_num, col_num):


return 2*row_num + col_num

F = np.fromfunction(f, (3, 3), dtype=int)


F

array([[0, 1, 2],
Out[19]:
[2, 3, 4],
[4, 5, 6]])

Printing arrays

In [20]:
dim1 = np.arange(15) # Create 1 1x15 matrix; n=1
dim2 = np.arange(15).reshape(3, 5) # Create 1 3x5 matrix; n=2
dim3 = np.arange(24).reshape(2, 3, 4) # Create 2 3x4 matrices; n=3

print(dim1, end='\t[1x15]\n\n')
print(dim2, end='\t[3x5]\n\n')
print(dim3, end='\t[2x3x4]')

[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] [1x15]

[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]] [3x5]

[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]

[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]] [2x3x4]

In [21]:
very_large = np.arange(10000).reshape(100, 100)
print(very_large) # printing a very large array

[[ 0 1 2 ... 97 98 99]
[ 100 101 102 ... 197 198 199]
[ 200 201 202 ... 297 298 299]
...
[9700 9701 9702 ... 9797 9798 9799]
[9800 9801 9802 ... 9897 9898 9899]
[9900 9901 9902 ... 9997 9998 9999]]
Common NumPy array operations

- Arithmetic operators on arrays apply elementwise.


- A new array is created and filled with the result.

In [22]:
a = np.arange(10)
b = np.array([2 for x in range(10)])
c = np.ones(10, dtype=int)
result = a + b - c # add 2 and subtract 1 from each element of a

print(result)

[ 1 2 3 4 5 6 7 8 9 10]

In [23]:
result **= 2 # square each element of result
result

array([ 1, 4, 9, 16, 25, 36, 49, 64, 81, 100])


Out[23]:

In [24]:
result < 10

array([ True, True, True, False, False, False, False, False, False,
Out[24]:
False])

In [25]:
a = np.ones(15).reshape(3, 5)
b = np.ones(15).reshape(5, 3)

mult = a * 10 # element-wise multiplication


dot_prod1 = a.dot(b) # dot product version 1
dot_prod2 = np.dot(a, b) # dot product version 2

print(mult, end='\n\n')
print(dot_prod1, end='\n\n')
print(dot_prod2)

[[10. 10. 10. 10. 10.]


[10. 10. 10. 10. 10.]
[10. 10. 10. 10. 10.]]

[[5. 5. 5.]
[5. 5. 5.]
[5. 5. 5.]]

[[5. 5. 5.]
[5. 5. 5.]
[5. 5. 5.]]

In [26]:
a, b = dot_prod1, dot_prod2

a += b # += and *= act in place -- they modify the existing array


a

array([[10., 10., 10.],


Out[26]:
[10., 10., 10.],
[10., 10., 10.]])

In [27]:
# array operations result in upcasting (result is more general type)
a = np.ones(10, dtype=int)
b = np.ones(10, dtype=float)
c = np.ones(10, dtype=complex)

a_plus_b = a + b # int + float


b_plus_c = b + c # float + complex

print(a_plus_b.dtype.name)
print(b_plus_c.dtype.name)

float64
complex128

In [28]:
# useful array methods
a = np.arange(1, 11)
print('Sum:', a.sum())
print('Min:', a.min())
print('Max:', a.max())

Sum: 55
Min: 1
Max: 10

In [29]:
# applying methods to a single axis
a = np.arange(15).reshape(3, 5) + 1

print(a.sum(axis=0)) # sum each column


print(a.min(axis=1)) # min of each row
a

[18 21 24 27 30]
[ 1 6 11]
array([[ 1, 2, 3, 4, 5],
Out[29]:
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])

Universal functions
In [30]:
# universal functions (sin, cos, exp, sqrt, ... etc)
a = np.linspace(0, 2*pi, 10000)

sin_a = np.sin(a)
sqrt_a = np.sqrt(a)
exp_a = np.exp(a)

print(sin_a, end='\n\n')
print(sqrt_a, end='\n\n')
print(exp_a, end='\n\n')

[ 0.00000000e+00 6.28381328e-04 1.25676241e-03 ... -1.25676241e-03


-6.28381328e-04 -2.44929360e-16]

[0. 0.02506754 0.03545085 ... 2.50637757 2.50650293 2.50662827]

[ 1. 1.00062858 1.00125755 ... 534.81909228 535.15526825


535.49165552]

Indexing, slicing, and iterating

In [31]:
# indexing elements from multidimensional arrays
A = np.array([x**2 for x in range(1, 11)]).reshape(2, 5)

print(A, end='\n\n')
print('A[0]\t\t', A[0])
print('A[-1]\t\t', A[-1])
print('A[0][0]\t\t', A[0][0])
print('A[-1][-1]\t', A[-1][-1])
#print('', A[])

[[ 1 4 9 16 25]
[ 36 49 64 81 100]]

A[0] [ 1 4 9 16 25]
A[-1] [ 36 49 64 81 100]
A[0][0] 1
A[-1][-1] 100

In [32]:
# slicing NumPy arrays
cubes = np.arange(1, 13).reshape(4, 3)**3 # cubes of 1-12

print(cubes[:,:], end='\n\n') # all rows, all cols


print('First Column:\t', cubes[:, 0]) # first col
print('Last Column:\t', cubes[:, -1]) # last col
print('First Row:\t', cubes[0, :]) # first row
print('Last Row:\t', cubes[-1, :]) # last row

[[ 1 8 27]
[ 64 125 216]
[ 343 512 729]
[1000 1331 1728]]

First Column: [ 1 64 343 1000]


Last Column: [ 27 216 729 1728]
First Row: [ 1 8 27]
Last Row: [1000 1331 1728]

In [33]:
# iterating through array elements
A = np.array([x+1 for x in range(10)])
A

array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Out[33]:

In [34]:
for a in A:
print(a, end=',')

1,2,3,4,5,6,7,8,9,10,

In [35]:
A = A.reshape(2, 5)

for a in A[0,:]: # for element in row 1


print(a**2, end=',')

1,4,9,16,25,

In [36]:
# Advanced: using ... for axis completion
A = np.arange(125).reshape(5, 5, 5) + 1

print('A[0, ...] == A[0, :, :]', end='\n\n')


print(A[0, ...], '\n\n', A[0, :, :])

A[0, ...] == A[0, :, :]

[[ 1 2 3 4 5]
[ 6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]]

[[ 1 2 3 4 5]
[ 6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]]

In [37]:
# flattening a 5x5x5 array for iteration
for a in A.flat:
print(a, end=',')

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,3
2,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,6
0,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,8
8,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,11
2,113,114,115,116,117,118,119,120,121,122,123,124,125,

Shape manipulation
Changing the shape of an array

In [38]:
a = np.floor(10*np.random.random((3, 4)))
print(a)
print(a.shape)

[[8. 2. 9. 3.]
[1. 3. 3. 1.]
[7. 2. 3. 4.]]
(3, 4)

In [39]:
a.ravel() # returns a COPY of the array flattened
array([8., 2., 9., 3., 1., 3., 3., 1., 7., 2., 3., 4.])
Out[39]:

In [40]:
a.reshape(6, 2) # returns a COPY of the array reshaped

array([[8., 2.],
Out[40]:
[9., 3.],
[1., 3.],
[3., 1.],
[7., 2.],
[3., 4.]])

In [41]:
a.T # returns a COPY of the array, transposed

array([[8., 1., 7.],


Out[41]:
[2., 3., 2.],
[9., 3., 3.],
[3., 1., 4.]])

In [42]:
print('A:\t', a.shape)
print('A^T:\t', a.T.shape)

A: (3, 4)
A^T: (4, 3)

In [43]:
A = np.floor(10*np.random.random((3, 4)))

A.reshape(4, 3) # reshape returns a COPY of A


print(A, 'array A remains unchanged')

A.resize(4, 3) # resize modifies array A


print(A, 'array A is of a new shape')

[[3. 8. 3. 8.]
[5. 8. 2. 0.]
[4. 4. 0. 2.]] array A remains unchanged
[[3. 8. 3.]
[8. 5. 8.]
[2. 0. 4.]
[4. 0. 2.]] array A is of a new shape

Stacking NumPy arrays horizontally and vertically

In [44]:
a = np.zeros(9, dtype=int).reshape(3, 3)
b = np.ones(9, dtype=int).reshape(3, 3)

# stack horizontally:
hor = np.hstack((a, b))
ver = np.vstack((a, b))

print('a:\n', a)
print('b:\n', b)
print('Horizontal Stack:\n', hor)
print('Vertical Stack:\n', ver)

a:
[[0 0 0]
[0 0 0]
[0 0 0]]
b:
[[1 1 1]
[1 1 1]
[1 1 1]]
Horizontal Stack:
[[0 0 0 1 1 1]
[0 0 0 1 1 1]
[0 0 0 1 1 1]]
Vertical Stack:
[[0 0 0]
[0 0 0]
[0 0 0]
[1 1 1]
[1 1 1]
[1 1 1]]

In [45]:
# similarly, row_stack and column_stack can be used to stack into 2D arrays
r_stack = np.row_stack((a, b))
c_stack = np.column_stack((a, b))

print('Horizontal Stack:\n', hor)


print('Vertical Stack:\n', ver)
print('Column Stack:\n', c_stack)
print('Row Stack:\n', r_stack)

Horizontal Stack:
[[0 0 0 1 1 1]
[0 0 0 1 1 1]
[0 0 0 1 1 1]]
Vertical Stack:
[[0 0 0]
[0 0 0]
[0 0 0]
[1 1 1]
[1 1 1]
[1 1 1]]
Column Stack:
[[0 0 0 1 1 1]
[0 0 0 1 1 1]
[0 0 0 1 1 1]]
Row Stack:
[[0 0 0]
[0 0 0]
[0 0 0]
[1 1 1]
[1 1 1]
[1 1 1]]

In [46]:
from numpy import newaxis

r_stack = np.row_stack((a[newaxis], b[newaxis]))


c_stack = np.column_stack((a[newaxis], b[newaxis]))

print('Column Stack:\n', c_stack)


print('Row Stack:\n', r_stack)

Column Stack:
[[[0 0 0]
[0 0 0]
[0 0 0]
[1 1 1]
[1 1 1]
[1 1 1]]]
Row Stack:
[[[0 0 0]
[0 0 0]
[0 0 0]]

[[1 1 1]
[1 1 1]
[1 1 1]]]

In [47]:
# use range literals to concatenate arrays on the fly
np.r_[1:5, 5, 6:10, 10]

array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Out[47]:

In [48]:
np.c_[1:5]

array([[1],
Out[48]:
[2],
[3],
[4]])

Splitting large arrays into smaller ones

In [49]:
# use hsplit or vsplit to split arrays
a = np.ones(9).reshape(3, 3)

a_1, a_2, a_3 = np.hsplit(a, 3) # split a into 3 arrays

print(a, end='\n\n')
print(a_1, end='\n\n')
print(a_2, end='\n\n')
print(a_3, end='\n\n')

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

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

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

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

Views and copies


No copy at all

In [50]:
a = np.arange(15).reshape(5, 3)
b = a
a is b

True
Out[50]:

View or shallow copy


In [51]:
# use the view() method to create a shallow copy of an array
a = np.array([x**2 for x in range(6)])
b = a.view()

print('a is b:', a is b)
print('a is b.base:', a is b.base)

b.shape = 3, 2

print(a.shape, ': no change to a\'s shape') # a's shape doesn't change

b[0, 1] = 1000

print(a, 'a\'s data has changed!')

a is b: False
a is b.base: True
(6,) : no change to a's shape
[ 0 1000 4 9 16 25] a's data has changed!

Deep copy

In [52]:
a = np.array([x+1 for x in range(10)])
b = a.copy()

print('a:', a, end='\t(Original)\n\n')
print('b:', b, end='\t(Deep Copy)\n\n')
print('a is b:', a is b)

a: [ 1 2 3 4 5 6 7 8 9 10] (Original)

b: [ 1 2 3 4 5 6 7 8 9 10] (Deep Copy)

a is b: False

You might also like