# 汪群超 Chun-Chao Wang

Dept. of Statistics, National Taipei University, Taiwan

# Lesson 1: Fundamentals

## Objective:

1. Prepare to do computations in Python.
2. Learn the necessary operations, functions and syntaxes for computations.
3. Learn to install, import and use modules, such as <b>numpy</b> and <b>scipy</b> in computations.

## Prerequisite:

• Install Python and Visual Studio Code (IDE) + python + Jupyter Notebook extensions.
• Be familiar with $\LaTeX$ so as to write math formula in Jupyter Notebook.

In VS Code ,open a new file (save as foo.py), try each of the following code, run and see the results.

#%% 1. Numbers

int_number = 1
float_number = 1.0
complex_number = 1 + 2j
round_float = round(1234.5678, 2)
str2int = int('213')

print(int_number)


Note:

1. To see the content of each variable, use print command, or check the JUPYTER:VARIABLES in VS Code.
2. Variable name is self-contained in this example.
3. The Python document has its format, e.g. variable = content1 + content2
# list and indexing

number_list = [0, 1, 1, 2, 3, 5, 8]
# the slicings use the zero-based indexing,
# that includes the lower bound and omit the upper bound, e.g.
print(number_list)  # indexing
print(number_list[0:3])  # [n, m] : slicing from index n to the mth position of the list
print(number_list[-1])  # the last one
print(number_list[-3:])  # the last three

list_list = [[1, 2, 3], [4, 5, 6]]  # list of list
print(list_list)
print(list_list[0:2])

# Explain why "indexing" starts from 0

a = [1, 2, 3, 4, 5, 6, 7]  # = np.arange(1, 8)
low, high = 2, 4
print(a[0:low] + a[low:high] + a[high:7])


# Vector and indexing

import numpy as np

a = np.array([1, 2, 3]) # a vector has no direction
A = np.array([[1, 2, 3]]) # a 1 x 3 array that can be transposed
a_T = a[:, np.newaxis] # a'
A_T = A.T # A'
C = np.array([1, 2, 3], ndmin = 2) # convert a to A
print(np.size(a))  # number of elements
print(np.shape(A_T))  # array dimension


Note:

1. Use numpy library. To install in terminal: pip install numpy.
2. Use np.size() and np.shape() to observe an array variable’s dimension.
3. Practice indexing for vector.
# Vector Indexing

A = np.array([[1, 2, 3],[4, 5, 6]])
print(A)
print(A.shape) # shape() is a method of a numpy array
print(A)
print(A[1,:])
print(A[:,1])
print(A[:,[0,2]])


# vector concatenate
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.concatenate((a, b), axis = 0) # flatten a, b
d = np.append(a, b)
e = np.hstack((a, b))
F = np.vstack((a, b))
g = np.r_[a, b]
G = np.c_[a, b]
H = (a, b)

#matrix concatenate

a = np.array([[1, 2, 3]])
b = np.array([[4, 5, 6]])

# Vertically, concatenate row-wisely
C = np.concatenate((a, b), axis = 0)
D = np.r_[a, b]
E = np.vstack((a,b))

# Horizontally, concatenate column-wisely
F = np.concatenate((a.T, b.T), axis =1)
G = np.hstack((a.T, b.T))
H = np.c_[a.T, b.T]

print(C)
print(C.max())
print(C.max(0)) # column max
print(np.max(C, axis = 1)) # row max


Note: The Difference Between a List and an Array in Python
Arrays and lists are both used in Python to store data, but they don’t serve exactly the same purposes. They both can be used to store any data type (real numbers, strings, etc), and they both can be indexed and iterated through, but the similarities between the two don’t go much further. The main difference between a list and an array is the functions that you can perform to them. For example, you can divide an array by 3, and each number in the array will be divided by 3 and the result will be printed if you request it. If you try to divide a list by 3, Python will tell you that it can’t be done, and an error will be thrown. (citation: Quick Tip: The Difference Between a List and an Array in Python)

tuple

a_tuple = (0, 0) # ordered sequence
also_a_tuple = 0, 0
a_3d_tuple = (0, 1, 2) # (2,1,0) is different, however the list  [0,1,2] := [1,2,0]


A = np.array([[1, 2, 3],[4, 5, 6]])
a = A.flatten() # turn into vector
b = A.flatten('F') # turn into vector column-wise
A[A < 3] = 0

c = [1, 2, 3, 4]
C = np.tile(c,(5,1)) # = repmat in MATLAB
d = np.reshape(C, (-1, 1)) # convert to Column vector
print(C)
print(d)
print(C.flatten())

Z = np.zeros((3,4))
One =  np.ones((3,4))
I = np.eye(3)
D = np.diag(c) # D a diagonal matrix
e = np.diag(I) # the diagonal of I


#%% string & indexing

s1 = 'a single quote string'
s2 = "a double quote string"
s3 = '''a triple quote string'''

print(type(s2))
print(s3)
print(s2[:4])
print(s3)

s4 = """
Triple double quotes
is usually used
in multiple lines, such as documents
"""

print(s4)

# concatenate strings
s5 = 'This is ' + s1
print(s5)

# string list
str_list = ['r', 'g', 'b', 'k', 'y']
print(str_list)

# Dictionaries similar to structure in MATLAB
meals = {'breakfast': 'sardines', 'lunch': 'salad', 'dinner': 'cake', 'cost':40}
print(meals['breakfast'])
print(meals['cost'])
print('The meal costs {} dollars'.format(meals['cost']))



import numpy as np

x0 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
x1 = range(1, 10, 1)
x2 = np.arange(1, 10, 1)  # integer
x3 = np.linspace(1, 9, 9)  # float number

x4 = np.arange(10)  # start from 0
x5 = np.linspace(0, 100, 1000)
# list and range type can not do math operations
y1 = x2 + x3 + 1
y2 = x2 ** 2 + x2 - 2
y3 = x2 / x3


Let $X = \left[ \begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ \end{array} \right] \;\;,$ $A = \left[ \begin{array}{ccc} 1 & 1 & 1 \\ 2 & 4 & 6 \\ 5 & 7 & 6 \end{array} \right]\;\;\;,$ $b = \left[ \begin{array}{c} 1 \\ 2 \\ 3 \end{array} \right]$

Find or compute the followings:
1. $X(1, 2)$
2. $A(i,j) = X(i,j) * X(i,j)$ for $1 \leq i \leq 2, 1\leq j\leq 3$
3. $B(i,j) = X(i,j) / X(i,j)$ for $1 \leq i \leq 2, 1\leq j\leq 3$
4. $C = XX^T$
5. total_sum $=\sum_{i=1}^{2}\sum_{j=1}^{3} X(i,j)$
6. row_sum $r_i=\sum_{j=1}^{3} X(i,j), 1\leq i \leq2$
7. col_sum $c_j=\sum_{i=1}^{2} X(i,j), 1\leq i\leq 3$
8. $x =A^{-1}b$
9. $I = AA^{-1}$
10. $A^2$
11. $\sqrt{A}$
12. $B = \left[ \begin{array}{c} A \\ b^T \end{array} \right]$, i.e. add a new row vector after the last row of A.
13. $C = \left[ \begin{array}{cc} A & b \end{array} \right]$, i.e. add a new column vector after the last column of A.
import numpy as np # numpy is a package
import scipy.linalg as LA # scipy's linear algebra is better

X = np.array([[1,2,3],[4,5,6]]) # a 2x3 matrix
# check the information of X
b = X.ndim
S = X.shape
s = X.size

a = X[0, 1]
A = X * X # element by element multiplication
B = X / X
C = X @ X.T # XX'

total_sum = X.sum() # X.mean()...
row_sum = X.sum(axis = 1) # sum over each row
# col_sum = X.sum(axis = 0) # sum over each column
col_sum = np.sum(X, axis = 0)

A = np.array([[1, 1, 1],[2, 4, 6],[5, 7, 6]])
b = np.array([1, 2, 3])
x =  LA.inv(A) @ b  # Ax = b
xsol = LA.solve(A, b) # Ax = b
I = A @ LA.inv(A)

A_square = matrix_power(A, 2) # nth power of a matrix
A_square_root = LA.fractional_matrix_power(A, 0.5)

B = np.vstack((A, b)) # 4 x 3
C = np.hstack((A, b.reshape(3, 1))) # 3 x 4

B_row = np.insert(A, 3, b, 0) # 3 is the position index; 0 is for row
B_col = np.insert(A, 3, b, 1) # 3 is the position index; 1 is for column


import numpy as np

x = np.array([1, 2, 5, 3, 2])
x[x > 3] = 9 # replaced by 9; conditioned on x>3
y = np.where(x > 3, 9, x)
z = np.where(x >=3, 1, 0)

a = 3
if a > 1 and a < 5 :
print('TRUE')
else :
print('FALSE')

if a > 5 or a < 1 :
print('OUTSIDE')
else :
print('INSIDE')