<jupyter_start><jupyter_text>NumPy (www.numpy.org)NumPy is important in scientific computing, it is coded both in Python and C (for speed). A few important features for Numpy are:a powerful N-dimensional array objectsophisticated broadcasting functionstools for integrating C/C++ and Fortran codeuseful linear algebra, Fourier transform, and random number capabilitiesNext, we will introduce Numpy arrays, which are related to the data structures.In order to use Numpy module, we need to import it first. A conventional way to import it is to use “np” as a shortened name using```pythonimport numpy as np```Numpy has a detailed guide for users migrating from Matlab. Just google 'Numpy for Matlab Users'<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>If the previously line produces an error, then you need to install numpy.Please type```python!pip install numpy ```<jupyter_code>#to create an array, we use the numpy funcion array
x = np.array([[1,2,3]])
x<jupyter_output><empty_output><jupyter_text>Arrays are entered by rows, each row is defined as a list. To create a 2d array, simply use nested lists<jupyter_code>y = np.array([[1,2,3],[4,5,6]])
y<jupyter_output><empty_output><jupyter_text>The arrays created with numpy are objects and have many atributes associated with them. For example, the shape of an array can be found with *shape*, and its size with *size*<jupyter_code>y.shape
y.size
x.shape
x.size<jupyter_output><empty_output><jupyter_text>You can access the elements in the array by index. There are multiple ways to access the element in the array<jupyter_code>x[0], x[1],x[2]
x[3]
y[0],y[0][0],y[0][1],y[0][2]
y[1],y[1][0],y[1][1],y[1][2]
y[0,0],y[0,1],y[0,2],y[1,0],y[1,1],y[1,2]<jupyter_output><empty_output><jupyter_text>In this form, the first index represents the row and the second index represents the column.You can also use slices to obtain a section of the array:<jupyter_code># What result will you obtain after this operation? 
y[:,:2]
# What result will you obtain after this operation? 
y[:,-2:]
# you an also access mutiple rows or columns by index
y[:,[0,1]]
y[:,[0,2]]<jupyter_output><empty_output><jupyter_text>NumPy includes methods to generate arrays that have a structure. - *arrange* -> generates arrays that are in order and evenly spaced,- *linspace* -> generates an array of n equally spaced elements starting from a defined begining and end points<jupyter_code># np.arange requires three parameters: 
# The starting point, the end point, and the increment

# NOTE: the end point is not inclusive

np.arange(0.5, 3, 0.5)
large_array = np.arange(0,2000,1)
large_array
large_array.size
# np.linspace requires three parameters: 
# The starting point, the end point, and 
# the number of elements

# NOTE: the end point is inclusive

np.linspace(0.5, 3, 6)
np.linspace(0, 1999, 2000)<jupyter_output><empty_output><jupyter_text>NumPy includes some predefined arrays that can make your life easier<jupyter_code>np.zeros((5,5))
np.zeros_like(y)
np.zeros((3,))
np.zeros_like(x)
np.ones((5, 5))
np.empty((5, 1))
np.empty((1,5))
np.empty((5))<jupyter_output><empty_output><jupyter_text>You can use the assigment operator to modify one or multiple elements in your array<jupyter_code># if you don't provide the increment, np.arange will
# use a default value of 1
a = np.arange(1, 7)
a
#to change the element in the index position 4, we can do
a[4] = 10
a
# to change the elements from 4 to the end we can do
a[4:] = [45,32]
a
#python will let you know if you made a mistake
a[4:] = [43,32,55]
# exercise
# to change the elements from index 2 to 5 (inclusive) to zero.
# we can do??
a[2:6] = np.zeros((1,4)) 
a<jupyter_output><empty_output><jupyter_text>Exercise:Create a zero array b with shape 2 by 2, and set $$    𝑏=\begin{bmatrix}1&2 \\ 3& 4\end{bmatrix}$$using array indexing.<jupyter_code>b = np.zeros((2,2))
b
b[0,0] = 1
b[0,1] = 2
b[1,0] = 3
b[1,1] = 4

b[0] = [1,2]
b[1] = [3,4]
b<jupyter_output><empty_output><jupyter_text>NumPy has powerful broadcasting abilities. You can do mathematical operation with arrays of different sizes and NumPy will take care of the operation if possible Operations with scalars<jupyter_code>b =  np.array([[0,1],[2,3]])
c = 2
b+c
b-c
b*c
b/c
b**c<jupyter_output><empty_output><jupyter_text>Operations between arrays<jupyter_code>b =  np.array([[0,1],[2,3]])
d =  np.array([[4,5],[6,7]])
b+d
b-d
b*d
b/d
b**d<jupyter_output><empty_output><jupyter_text>The *, /, and ** operations are operating on an element by element basis.   Operations between arrays of different sizes<jupyter_code>b =  np.array([[0,2],[3,4]])
d =  np.array([[4],[5]])
b+d<jupyter_output><empty_output><jupyter_text>Can you explain what is going on?<jupyter_code>b-d
b*d
b/d
b**d<jupyter_output><empty_output><jupyter_text>Matrix Multiplication<jupyter_code>b =  np.array([[0,1],[2,3]])
d =  np.array([[4,5],[6,7]])
e =  np.array([[4],[5]])
f =  np.array([[4,5]])
b@d, np.matmul(b,d)
b@e
# NumPy will tell you when you make a mistake
b@f
# the .T atributes computes the transpose of a matrix
# it has precedence over other operations
b@f.T<jupyter_output><empty_output><jupyter_text>NumPy can also apply logical operations between arrays and scalars or between two arrays of the same size<jupyter_code>x = np.array([1, 2, 4, 5, 9, 3])
y = np.array([0, 2, 3, 1, 2, 3])
x>3<jupyter_output><empty_output><jupyter_text>Python can index elements of an array that satisfy a logical expression.<jupyter_code>x[x>3]
# you can also use multiple conditions 
x[np.logical_or(x<3,x>=5)]
x[np.logical_and(x<=9,x>=5)]<jupyter_output><empty_output><jupyter_text>you can also use the assignment operator to modify an array based on conditions<jupyter_code>y = x[x>3]
y
y[y>=9] = 0
y<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup