Python Basics

Please refer to python 3 documentation

Numpy and Linear Algebra

In [1]:
import numpy as np
# Creating two lists, a and b
a=[1,2,3] 
b=[4,5,6]
c=np.concatenate((a,b))
print(c)
[1 2 3 4 5 6]
In [2]:
## Logial operations are element-wise ##
# Create an array
f = np.array([1,2,3,4,5])
print('This is the frist output: ',f < 4)
print('This is the second output: ',(f<4) | (f>4)) # | is logical symbol for 'or'
This is the frist output:  [ True  True  True False False]
This is the second output:  [ True  True  True False  True]
In [3]:
## Sums and Averages of elements inside array##
g = np.array([[1,2,3],[4,5,6]])
print(g)
g.sum()
[[1 2 3]
 [4 5 6]]
Out[3]:
21
In [4]:
g.sum(axis=1)
Out[4]:
array([ 6, 15])
In [5]:
g.mean()
Out[5]:
3.5
In [6]:
g.std()
Out[6]:
1.707825127659933
In [7]:
# If we are not sure what a function or object is, then
# we can look to the help page.
help(g.std)
Help on built-in function std:

std(...) method of numpy.ndarray instance
    a.std(axis=None, dtype=None, out=None, ddof=0, keepdims=False)
    
    Returns the standard deviation of the array elements along given axis.
    
    Refer to `numpy.std` for full documentation.
    
    See Also
    --------
    numpy.std : equivalent function

In [8]:
g.std(axis=1)
Out[8]:
array([0.81649658, 0.81649658])
In [9]:
# Take two matrices, a and b, then concatenate them.
a=np.array([[1,2,3],[4,5,6]])
b=np.array([[1,2,3],[7,8,9]])
c=np.concatenate((a,b))
print(c)
[[1 2 3]
 [4 5 6]
 [1 2 3]
 [7 8 9]]
In [10]:
d = np.transpose(c) # transpose of c
f = d[:,0:3] # first 3 columns of d
g = np.eye(3) # identity 3x3
h = np.concatenate((f,g), axis=0) # linking f and g
I = np.concatenate((f,g), axis=1) # linking f and g
print(I) # axis=1
[[1. 4. 1. 1. 0. 0.]
 [2. 5. 2. 0. 1. 0.]
 [3. 6. 3. 0. 0. 1.]]

Matrices with sympy

In [11]:
# Lets use sympy to construct a matrix
## Matrices from docs.sympy.org ##
from sympy import *
# We can also make the output look pretty
init_printing(use_unicode=True)
M = Matrix([[1,2,3],[4,5,6],[7,8,9]])
print('Row Reduce Echelon Form of the Matrix M is:\n')
M.rref()
Row Reduce Echelon Form of the Matrix M is:

Out[11]:
$$\left ( \left[\begin{matrix}1 & 0 & -1\\0 & 1 & 2\\0 & 0 & 0\end{matrix}\right], \quad \left ( 0, \quad 1\right )\right )$$
In [12]:
print("See, we can still print, but it doesn't look as nice\n",M)
See, we can still print, but it doesn't look as nice
 Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
In [13]:
A = Matrix([[1,2,3],[4,5,6],[7,8,9]])
In [14]:
# If you need an immutable version of Matrix, use ImmutableMatrix
A.shape
Out[14]:
$$\left ( 3, \quad 3\right )$$
In [15]:
# to get individual rows of columns, use:
A.row(0)
A.col(1)
Out[15]:
$$\left[\begin{matrix}2\\5\\8\end{matrix}\right]$$
In [16]:
# deleting and inserting rows and columns
A.row_del(1)
A
Out[16]:
$$\left[\begin{matrix}1 & 2 & 3\\7 & 8 & 9\end{matrix}\right]$$
In [17]:
A.T
Out[17]:
$$\left[\begin{matrix}1 & 7\\2 & 8\\3 & 9\end{matrix}\right]$$
In [18]:
A = Matrix([[2,3,4],[5,8,3],[3,3,3]])
A
Out[18]:
$$\left[\begin{matrix}2 & 3 & 4\\5 & 8 & 3\\3 & 3 & 3\end{matrix}\right]$$
In [19]:
A.rref() # (rref, pivot columns)
Out[19]:
$$\left ( \left[\begin{matrix}1 & 0 & 0\\0 & 1 & 0\\0 & 0 & 1\end{matrix}\right], \quad \left ( 0, \quad 1, \quad 2\right )\right )$$
In [20]:
A.nullspace()
Out[20]:
$$\left [ \right ]$$
In [21]:
B = Matrix([[1,2,3],[4,5,6],[7,8,9]])
B
Out[21]:
$$\left[\begin{matrix}1 & 2 & 3\\4 & 5 & 6\\7 & 8 & 9\end{matrix}\right]$$
In [22]:
B.rref()
Out[22]:
$$\left ( \left[\begin{matrix}1 & 0 & -1\\0 & 1 & 2\\0 & 0 & 0\end{matrix}\right], \quad \left ( 0, \quad 1\right )\right )$$
In [23]:
B.nullspace()
Out[23]:
$$\left [ \left[\begin{matrix}1\\-2\\1\end{matrix}\right]\right ]$$
In [24]:
## Eigenvalues and Eigenvectors ##
A.eigenvals() # returns (eigenvalue:algebraic multiplicity)
Out[24]:
$$\left \{ -1 : 1, \quad 2 : 1, \quad 12 : 1\right \}$$
In [25]:
A.eigenvects()
# which returns (eigenvalue:algebraic multiplicity, [eigenvectors])
Out[25]:
$$\left [ \left ( -1, \quad 1, \quad \left [ \left[\begin{matrix}- \frac{9}{4}\\\frac{11}{12}\\1\end{matrix}\right]\right ]\right ), \quad \left ( 2, \quad 1, \quad \left [ \left[\begin{matrix}1\\- \frac{4}{3}\\1\end{matrix}\right]\right ]\right ), \quad \left ( 12, \quad 1, \quad \left [ \left[\begin{matrix}1\\2\\1\end{matrix}\right]\right ]\right )\right ]$$
In [26]:
## dagonlizable matrices ##
#  A = PDP^-1
P, D = A.diagonalize()
print(P)
print(D)
Matrix([[-27, 3, 1], [11, -4, 2], [12, 3, 1]])
Matrix([[-1, 0, 0], [0, 2, 0], [0, 0, 12]])
In [27]:
# remember that lambda is a reserved keyword in python, so
# to create the symbol use: lamda (without the 'b')

lamda = symbols('lamda')

B = Matrix([[1, 0 , 1],[1, 1, 2], [ 1, 0, 1]])
B

b = B.charpoly(lamda)
b

factor(b)
Out[27]:
$$\lambda \left(\lambda - 2\right) \left(\lambda - 1\right)$$

Scipy and Matplotlib Plotting

In [28]:
x = symbols('x')
y = x**2 + 5*x + 6
print(y)
x**2 + 5*x + 6
In [29]:
y_x = integrate(y)
pprint(y_x)
 3      2      
x    5â‹…x       
── + ──── + 6⋅x
3     2        
In [30]:
## Constructing a large lil_matrix and add values to it ##
from scipy.sparse import lil_matrix
from scipy.sparse.linalg import spsolve
from numpy.linalg import solve, norm
from numpy.random import rand
## Optimization ##
#Minimization (steepest-decentm conjugate gradient), curve-fitting, least squares, root finding (Newton's method), annealing, etc. 
import scipy.optimize as optimize
In [31]:
## Curve Fitting Example ##
def func(x,a,b,c):
    return a*np.exp(-b*x) + c
In [32]:
x = np.linspace(0,4,50) # 50 values linearly in [0,4]
y = func(x,2.5,1.3,0.5)
yn = y + 0.2*np.random.normal(size=len(x))
popt,pcov = optimize.curve_fit(func,x,yn)
popt,pcov # optimized parameters and their covariance
Out[32]:
(array([2.68646283, 1.51320963, 0.53692262]),
 array([[ 0.01767912,  0.00851316, -0.00063102],
        [ 0.00851316,  0.02293804,  0.00501921],
        [-0.00063102,  0.00501921,  0.00242487]]))
In [33]:
## Matplotlib ##
from matplotlib.pyplot import *
from pylab import *
x = np.arange(0,10,0.2)
y = np.cos(x)
figure()
Out[33]:
<Figure size 640x480 with 0 Axes>
In [34]:
plot(x,y,'g*')
show()
In [35]:
# or we can show the figure inline
%matplotlib inline
plot(x,-np.exp(2*y),'g*')
Out[35]:
[<matplotlib.lines.Line2D at 0x1015127320>]

Control/Conditional Statements

In [36]:
## Contidtionsl and Flow Statements ##

## 'if' Statement
x = int(1) # Change the initial condition to alt output
if x < 0:
    x = 0
    print('Negative goes to zero')
elif x == 0:
    print('Zero')
elif x == 1:
    print('single')
else:
    print('More')
single
In [37]:
##  Examples using 'for' statement
# create a list of names
Names = ['Rob', 'Ron', 'Felish', 'George', 'Shoe']
for x in Names:
    # print the ith element of the list, followed by 
    # the number of charecters the name has. 
    print(x, len(x))

# Here's another way to do the same thing...
# but let x be the ith iteration.
Names = ['Rob', 'Ron', 'Felish', 'George', 'Shoe']
for i in range(len(Names)):
    print(i,Names[i])
Rob 3
Ron 3
Felish 6
George 6
Shoe 4
0 Rob
1 Ron
2 Felish
3 George
4 Shoe
In [38]:
for x in range(5):    # range(5) = {0,1,2,3,4}
    if x == 3:        # if x=3, print out the string
        print('Three')
    elif x == 0:      # "elseif" needed after 'if' to continue with condiditions of the same statement
        print('Zero')
    else:             # otherwise, print out the remaining
        print(x)
Zero
1
2
Three
4
In [39]:
for x in Names[:]: # Loops over a slice copy of the entire list.
    if len(x) > 5:
        Names.remove(x)
        Names.append('Name')
        
Names
Out[39]:
['Rob', 'Ron', 'Shoe', 'Name', 'Name']
In [40]:
## 'break' and 'continue' Statements, and 'else' Clauses on loops
## Prime Numbers ##
for n in range(2,50):
    for x in range(2, n):
        if n % x == 0:
            print(n, '=', x, '*', n/x)
            break
    else:
        # loop fell through without finding a factor
        print(n, 'is a prime number')
        
2 is a prime number
3 is a prime number
4 = 2 * 2.0
5 is a prime number
6 = 2 * 3.0
7 is a prime number
8 = 2 * 4.0
9 = 3 * 3.0
10 = 2 * 5.0
11 is a prime number
12 = 2 * 6.0
13 is a prime number
14 = 2 * 7.0
15 = 3 * 5.0
16 = 2 * 8.0
17 is a prime number
18 = 2 * 9.0
19 is a prime number
20 = 2 * 10.0
21 = 3 * 7.0
22 = 2 * 11.0
23 is a prime number
24 = 2 * 12.0
25 = 5 * 5.0
26 = 2 * 13.0
27 = 3 * 9.0
28 = 2 * 14.0
29 is a prime number
30 = 2 * 15.0
31 is a prime number
32 = 2 * 16.0
33 = 3 * 11.0
34 = 2 * 17.0
35 = 5 * 7.0
36 = 2 * 18.0
37 is a prime number
38 = 2 * 19.0
39 = 3 * 13.0
40 = 2 * 20.0
41 is a prime number
42 = 2 * 21.0
43 is a prime number
44 = 2 * 22.0
45 = 3 * 15.0
46 = 2 * 23.0
47 is a prime number
48 = 2 * 24.0
49 = 7 * 7.0
In [41]:
## Even and Odd example
for n in range(2, 10):
    if n % 2 == 0:
        print('Found an even number', n)
        continue
    print('Found an odd number', n)

## 'pass' Statements

# pass statement does nothin.  It can be used requires no action.
# It can be used for creaing minimal classes.
# It can also be used as a place-holder for a function
def initlog(*arguments):
    pass  # remember to implement this!
Found an even number 2
Found an odd number 3
Found an even number 4
Found an odd number 5
Found an even number 6
Found an odd number 7
Found an even number 8
Found an odd number 9

Creating Methods

In [42]:
## Defining Functions ##
def fib(n):  # write Fibonacci series up to n
    """Print a Fibonacci series up to n."""
    a,b = 0,1
    while a < n:
        print(a,)
        a,b = b,a+b
        
# Now, calling on the function just made
fib(2000)
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
In [43]:
## changing fib to fib2
def fib2(n):  # write Fibonacci series up to n
    """Return a list containing the Fibonacci series up to n."""
    result = []
    a,b = 0,1
    while a < n:
        result.append(a) 
        a,b = b,a+b
    return result
        
fib2(100)
Out[43]:
$$\left [ 0, \quad 1, \quad 1, \quad 2, \quad 3, \quad 5, \quad 8, \quad 13, \quad 21, \quad 34, \quad 55, \quad 89\right ]$$
In [44]:
 #The return statement returns with a value from a function.
 #return without an expression arugment returns None.
 #The statement result.append(a) calls a method of the list object result.
 #A method i a function that belongs to an object and is named obj.methodname

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))
print(f(100))
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 100]
In [45]:
# If you dont want the default to be shared with subsequent calls...
def f(a, L=None):
    if L is None:
        L = [] # generate a new list every iteration
    L.append(a)
    return L

print(f(0))
print(f(1))
print(f(2))
print(f(100))
[0]
[1]
[2]
[100]
In [46]:
## Keyword Arguments ##
# which are of the form: kwarg=value
# In general:
# def func(required, state, action, type):

# lets make one up...
food=['apple', 'organges', 'bread', 'salad']
def store(food, state='need', action='buy', type='cash'):
    if food == 'salad':
        print('This store has the groceries I', state,',' )
        print("but doesn't have", food, )
    elif food == 'organges':
        print('They have', food, 'but I have insignificant', type,)
    
In [47]:
store('salad')
# This needs work (not finished)
This store has the groceries I need ,
but doesn't have salad
In [48]:
## The template for writing a function ##

def my_function():
    '''Insert a short, concise summary of the object's purpose.'''
    pass

print(help(my_function)) # just showing the docstring for the function
Help on function my_function in module __main__:

my_function()
    Insert a short, concise summary of the object's purpose.

None

Strings

In [41]:
name = 'Enter Name Here'  # Enter your name here
intro = 'Hello, my name is %s.'%(name)

## Let's do some string minipulation...

# First, lets separate this statement by each space 
# we can put each word into a list 
List = [word for word in intro.split(" ")]
print(List)
['Hello,', 'my', 'name', 'is', 'Enter', 'Name', 'Here.']
In [42]:
# We can get rid of any punctuation marks with replace
List = [word.replace(".","").replace(",","") for word in intro.split(" ")]
print(List)
['Hello', 'my', 'name', 'is', 'Enter', 'Name', 'Here']
In [43]:
# We can print the length of the list (number of words)
print(len(List))
7
In [44]:
# We can print the length of each element in the list (number of characters)
nChar = 0  # start a count of the number of characters 
for i in range(len(List)):
    nChar += len(List[i])
    print('Word %i/%i has %i characters.'%(i+1,len(List),len(List[i])))
print('The total number of characters in the list is %i'%nChar)
Word 1/7 has 5 characters.
Word 2/7 has 2 characters.
Word 3/7 has 4 characters.
Word 4/7 has 2 characters.
Word 5/7 has 5 characters.
Word 6/7 has 4 characters.
Word 7/7 has 4 characters.
The total number of characters in the list is 26

Pandas intro using DataFrame

In [71]:
import pandas as pd
%matplotlib inline
In [72]:
m = 5  # number of participants or "members"
n = 10 # number of observations of position

observation_times = pd.Series(["01-%0.2i-2020"%i for i in range(n)])
# You can do the same thing using:  dates_index = pd.date_range("20200101", periods=m)
array = np.random.random((n,m)) # creating a bunch (n x m) of random samples
samples = pd.DataFrame(array, index=observation_times, columns=["m%i"%i for i in range(m)])
samples
Out[72]:
m0 m1 m2 m3 m4
01-00-2020 0.937316 0.368824 0.042178 0.684397 0.858460
01-01-2020 0.357470 0.773069 0.240093 0.959584 0.356147
01-02-2020 0.256263 0.691304 0.899965 0.712793 0.191974
01-03-2020 0.589598 0.129081 0.053418 0.969236 0.409405
01-04-2020 0.259605 0.553429 0.264450 0.723184 0.931979
01-05-2020 0.405190 0.904864 0.120987 0.358477 0.478887
01-06-2020 0.062946 0.452185 0.041786 0.311089 0.728425
01-07-2020 0.659022 0.717208 0.614267 0.295837 0.863187
01-08-2020 0.299028 0.320972 0.071031 0.060101 0.430828
01-09-2020 0.102177 0.535229 0.752860 0.483881 0.318303
In [73]:
# gather specific memembers
sub_samples = samples[["m2","m4"]] # grabbing only the 2nd and 4th members
sub_samples
Out[73]:
m2 m4
01-00-2020 0.042178 0.858460
01-01-2020 0.240093 0.356147
01-02-2020 0.899965 0.191974
01-03-2020 0.053418 0.409405
01-04-2020 0.264450 0.931979
01-05-2020 0.120987 0.478887
01-06-2020 0.041786 0.728425
01-07-2020 0.614267 0.863187
01-08-2020 0.071031 0.430828
01-09-2020 0.752860 0.318303
In [74]:
sub_samples.sum()  # sum up the two columns over all timestamps
Out[74]:
m2    3.101033
m4    5.567595
dtype: float64
In [75]:
# Subtract the element one row up from the current row
subtract = sub_samples.diff(periods=1, axis=0)
subtract.fillna(0)
Out[75]:
m2 m4
01-00-2020 0.000000 0.000000
01-01-2020 0.197915 -0.502313
01-02-2020 0.659872 -0.164173
01-03-2020 -0.846547 0.217431
01-04-2020 0.211032 0.522575
01-05-2020 -0.143463 -0.453093
01-06-2020 -0.079201 0.249538
01-07-2020 0.572481 0.134762
01-08-2020 -0.543235 -0.432359
01-09-2020 0.681829 -0.112526
In [76]:
# Subtract one column with the other
diff = sub_samples.diff(periods=1, axis=1)
diff.fillna(0)
Out[76]:
m2 m4
01-00-2020 0.0 0.816282
01-01-2020 0.0 0.116054
01-02-2020 0.0 -0.707991
01-03-2020 0.0 0.355987
01-04-2020 0.0 0.667530
01-05-2020 0.0 0.357900
01-06-2020 0.0 0.686640
01-07-2020 0.0 0.248920
01-08-2020 0.0 0.359797
01-09-2020 0.0 -0.434557
In [77]:
# Another way of getting a subset...
subset = samples[1:4]
In [78]:
subset.plot()
Out[78]:
<matplotlib.axes._subplots.AxesSubplot at 0x1261b92d0>
In [79]:
subset.T # transpose the subset
Out[79]:
01-01-2020 01-02-2020 01-03-2020
m0 0.357470 0.256263 0.589598
m1 0.773069 0.691304 0.129081
m2 0.240093 0.899965 0.053418
m3 0.959584 0.712793 0.969236
m4 0.356147 0.191974 0.409405
In [80]:
# Create a series of the first day of the year
#series = (subset.T)["01-01-2020"]
# Or you can use...
series = (subset.T)[subset.index[0]]
series
Out[80]:
m0    0.357470
m1    0.773069
m2    0.240093
m3    0.959584
m4    0.356147
Name: 01-01-2020, dtype: float64
In [81]:
# Delete the last member of this series
series.values
Out[81]:
array([0.35746958, 0.77306934, 0.24009301, 0.95958382, 0.35614682])
In [ ]:
 
In [ ]: