Programming basics for Biostatistics 6099

functions and modules

Zhiguang Huo (Caleb)

Thursday Oct 19th, 2023

Outlines

Writing Basic Python functions

def hello():
    print('Hello World!')

hello()
## Hello World!
def hello(name):
    print('Hello, ' + name + "!")

hello("Lucas")
## Hello, Lucas!

Function Descriptions and Helps

def inc(x): 
  """Increase by one
  
  Keyword arguments:
  x -- the base number to be increased
  """
  return x + 1

inc(3)
## 4
inc.__doc__ ## check docstring
## 'Increase by one\n  \n  Keyword arguments:\n  x -- the base number to be increased\n  '
?inc
help(inc)

Function structure

Recursive function

def factorial(n):
    result = n
    for i in range(1,n):
        result *= i
    return result

factorial(5)
## 120
def factorial(n):
    if n==1: return 1
    return n*factorial(n-1)

factorial(5)
## 120

In class exercise

def fibonacci(n):
    if(n<=1):
        return(1)
    else:
        return(fibonacci(n-1) + fibonacci(n-2))

fibonacci(4)
## 5
fibonacci(5)
## 8

Some built-in Python functions

abs(-4)
## 4
pow(2,3) ## 2**3
## 8
round(3.14)
## 3
max(6,9)
## 9
min([1,2,3,7])
## 1
sum(range(10))
## 45
help(sum)
## Help on built-in function sum in module builtins:
## 
## sum(iterable, /, start=0)
##     Return the sum of a 'start' value (default: 0) plus an iterable of numbers
##     
##     When the iterable is empty, return the start value.
##     This function is intended specifically for use with numeric values and may
##     reject non-numeric types.
?sum ## this way only works for Jupyter Notebook

Module

def hello(name):
    print('Hello ' + name + '!')
def myadd(a, b):
    return(a + b)
import mymod

mymod.hello("Lucas")
## Hello Lucas!
mymod.myadd(1, 10)
## 11

Module

Student1 = {
  "name": "Amy",
  "age": "23",
  "country": "Canada"
}
import mymod

astudent = mymod.Student1
print(astudent)
## {'name': 'Amy', 'age': '23', 'country': 'Canada'}
for akey in astudent:
        print(akey + ": " + astudent[akey])
## name: Amy
## age: 23
## country: Canada

math modules

After import module, all the objects in the module are available via module.object

import math

math.sqrt(3)
## 1.7320508075688772
math.floor(10.4)
## 10
math.ceil(10.4)
## 11
math.log(16,2)
## 4.0
math.log2(16)
## 4.0
math.pi
## 3.141592653589793

math modules

import math as m
m.pi
## 3.141592653589793
from math import pi
pi
## 3.141592653589793
from math import pi, log2
log2(pi)
## 1.6514961294723187

os module

import os
cwd = os.getcwd() ## get current working directory
print("Current working directory is " + cwd)
## Current working directory is /Users/zhuo/Dropbox (UFL)/teaching/2023FALL/lectures/Week10_functions/functions
os.listdir() 
## os.listdir(cwd)  same as this one
## ['.Rhistory', 'functions.py', 'functions.rmd', '.DS_Store', 'functions.html', '__pycache__', '.ipynb_checkpoints', 'mymod.py', 'tmp']
os.chdir('..') ## go back one folder
os.getcwd()
## '/Users/zhuo/Dropbox (UFL)/teaching/2023FALL/lectures/Week10_functions'
os.chdir(cwd) ## go back to cwd
os.getcwd()
## '/Users/zhuo/Dropbox (UFL)/teaching/2023FALL/lectures/Week10_functions/functions'
os.mkdir("tmp") ## create a single folder
os.makedirs("foo/bar")  ## create a recursive folder
os.remove(afile) ## remove afile
os.rmdir(afolder) ## remove a folder
file = 'Untitled.ipynb'
      
# File location 
location = "/Users/zhuo/Desktop/" ## change this to your own directory
os.listdir(location)
      
# Path 
## ['.Rhistory', 's41592-021-01252-x.pdf', 'fdgth-03-727504.pdf', 'Screen Shot 2023-09-28 at 8.55.01 AM.png', '~$deed.docx', 'BayesianCircadianSlides.pptx', 'GatorPKG', 'drugs and insurance.txt', '.DS_Store', 'Jupyter_note.PNG', 'PIIS0092867421003792.pdf', 'LOI.pdf', 'NFWF_Data_Management_and_Access_Plan.pdf', 'GrantApplication.pdf', '.localized', 'Untitled.ipynb', 'Gator2022', 'example', 'Screen Shot 2023-10-18 at 11.22.40 AM.png', 'Screen Shot 2023-10-02 at 3.55.26 PM.png', 'Ding_GA-Work-Schedule.pdf', 'shiny-examples', 'Screen Shot 2023-10-10 at 11.36.11 AM.png', 'others', 'circadianWebsite', 'wga.pdf', '2024_Dental_Monthly_Premium_Chart.pdf', 'This manuscript studies the potential causal relationship between sleep behavior and renal outcomes.docx', 'budget_justification_SOMOA_Huo 051823.pdf', 'Screen Shot 2023-09-21 at 1.38.12 PM.png', 'chatGPT.txt', 'budget_justification_SOMOA_Huo 051823 (1).pdf', 'YCR-2021-2022-AcademicSalaryReport.pdf', 'Auto-GPT', 'JEV template (1).pdf', 'Action Required_ Proposal SFI Certification Requested PI_ Esser.eml', 'openAI_key.txt', 'Committee_Change_Form_Dongyuan.pdf', 'Personalized glucose respoinses Naef Cell Reports 08042023.pdf', 'eamm', 'bbaa257.pdf', '.ipynb_checkpoints', 'Screen Shot 2023-10-04 at 12.50.24 PM.png', 'J American Geriatrics Society - 2018 - Rogers‐Soeder - Rest‐Activity Rhythms and Cognitive Decline in Older Men  The.pdf', 'Mail - Huo,Zhiguang - Outlook_files', '2024_Dental_Plan_Comparison_(Final).pdf', 'Screen Shot 2023-10-05 at 10.23.28 AM.png', 'Screen Shot 2023-09-21 at 1.38.20 PM.png', 'Screen Shot 2023-10-10 at 11.35.17 AM.png', 'thumbnail_image.png']
path = os.path.join(location, file) 
print(path)
## /Users/zhuo/Desktop/Untitled.ipynb
os.path.exists(location) 
## True
os.path.exists(path) 
## True
os.path.isfile(path) 
## True
os.path.isdir(location) 
## True

random module

import random

print(random.random())
## 0.16687382761630964
random.seed(10)
print(random.random())
## 0.5714025946899135
random.seed(10)
print(random.random())
## 0.5714025946899135

random integer

print(random.randint(1, 3))
## 2
print(random.randrange(1, 3))
## 2

random choices and shuffle

mylist = ["apple", "banana", "cherry"]
random.choice(mylist)
## 'cherry'
random.choices(mylist, k = 2)
## ['apple', 'banana']
random.shuffle(mylist)
mylist
## ['apple', 'cherry', 'banana']

Default arguments

def add(arg1 = 1, arg2 = 2):   
    return(arg1 + arg2)

add(arg1 = 3, arg2 = 4)
## 7
add(arg1 = 3)
## 5
add()
## 3

Function arguments matching rule

def parrot(arg, brg=["a", "b"], crg='python'):
    print("arg: " + str(arg))
    print("brg: " + str(brg))
    print("crg: " + str(crg))
parrot(1000)                             # 1 positional argument
## arg: 1000
## brg: ['a', 'b']
## crg: python
parrot(arg=1000)                         # 1 keyword argument
## arg: 1000
## brg: ['a', 'b']
## crg: python
parrot(arg=1000000, crg='R')             # 2 keyword arguments
## arg: 1000000
## brg: ['a', 'b']
## crg: R
parrot(crg='JAVA', arg=1000000)             # 2 keyword arguments
## arg: 1000000
## brg: ['a', 'b']
## crg: JAVA
parrot(32611, [1,2,3], "C++")         # 3 positional arguments
## arg: 32611
## brg: [1, 2, 3]
## crg: C++
parrot(567, brg=list("abc"))  # 1 positional, 1 keyword
# parrot(brg=list("abc"), 567)  # 1 positional, 1 keyword, doesn't work
## arg: 567
## brg: ['a', 'b', 'c']
## crg: python

Extra arguments

def add(a,b):
  return(a + b)
def add(a,b,c,d):
  return(a + b + c + d)

Extra arguments

def print_args(*args):
    print(args)

print_args('Testing') ## tuple of length 1
## ('Testing',)
print_args(1,2,3)
## (1, 2, 3)
def print_args_2(title, *args):
    print(title)
    print(args)

print_args_2("Args:", 1,2,3)
## Args:
## (1, 2, 3)
print_args_2("Nothing:")
## Nothing:
## ()

In class exercise

add(1,2,3,4,5) # 15
add(1,2,3,4,5,6,7,8,9,10) # 55
def add(*args):
    print(type(args)) ## the input args forms a tuple
    sum = 0
    for n in args:
        sum += n
    return sum

add(1,2,3,4,5) # 15
## <class 'tuple'>
## 15
add(1,2,3,4,5,6,7,8,9,10) # 55
## <class 'tuple'>
## 55

Extra keywords

def print_keywords_3(**keywords):
    print(keywords)

print_keywords_3(x=1,y=2,z=3)
## {'x': 1, 'y': 2, 'z': 3}
def print_keywords_4(**keywords):
    for kw in keywords:
        print(kw, ":", keywords[kw])
print_keywords_4(x=1,y=2,z=3)
## x : 1
## y : 2
## z : 3
def print_params_4(x,y,z=3,*pospar, **keypar):
    print(x,y,z)
    print(pospar)
    print(keypar)

print_params_4(x=1,y=2)
## 1 2 3
## ()
## {}
print_params_4(1,2,3,5,6,7,foo=1)
## 1 2 3
## (5, 6, 7)
## {'foo': 1}

Assertion

assert expression[, assertion_message]
number = 1 ## try -1 as well
assert number > 0
assert number > 0, f"number greater than 0 expected, got: {number}"

Lambda function

def f1(x):
    return(x + 10)

f1(5)
## 15
f2 = lambda x : x + 10

f2(5)
## 15
(lambda x : x + 10)(5)
## 15

Lambda function with more than 1 argument

def f3(a,b):
  return(a*b)

f3(5,6)
## 30
f4 = lambda a, b : a * b
print(f4(5, 6))
## 30

Function scopes

x = 300

def afun():
  print(x)

afun()
## 300
print(x)
## 300

Function scopes

x = 300

def afun():
  x = 200
  print(x)

afun()
## 200
print(x)
## 300

Function scopes

def bfun():
  global x
  x = 50

bfun()
print(x)
## 50
x = 50

def bfun():
  global x
  x = 60

bfun()
print(x)
## 60

Multiple return values

def f23(x):
    x_square = x**2
    x_cubic = x**3
    res_tuple = (x_square, x_cubic)
    return(res_tuple)

f23(3)
## (9, 27)
a, b = f23(5) ## to receive multiple return values
print(a)
## 25
print(b)
## 125

Other looping technique

d = ["a", "b", "c"]
e = [1, 2, 3]

zip(d,e) 
## <zip object at 0x119aa1e40>
list(zip(d,e))
## [('a', 1), ('b', 2), ('c', 3)]
for i, j in zip(d,e):
    print(i + str(j))
## a1
## b2
## c3
a = zip(d,e)
next(a)
d = ["a", "b", "c"]
for index, string in enumerate(d):
    print(string + str(index))
## a0
## b1
## c2
list(enumerate(d))
## [(0, 'a'), (1, 'b'), (2, 'c')]
x = enumerate(d) ## iterable object
next(x)
## (0, 'a')

list comprehension

squares = []
for x in range(10):
    squares.append(x**2)

squares
## [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[x**2 for x in range(10)]
## [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

list comprehension

[(i,j) for i in range(3) for j in range(3)]
## [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
[i for i in range(10) if i%2==0 ]
## [0, 2, 4, 6, 8]
names = ["Amy", "Beth", "Carl"]
[aname[0] for aname in names]
## ['A', 'B', 'C']

list comprehension for dictionary

names = ["Amy", "Beth", "Carl", "Dan", "Emily", "Frank"]

import random

students_scores = {name: random.randint(0, 100) for name in names}

students_scores
## {'Amy': 83, 'Beth': 20, 'Carl': 4, 'Dan': 66, 'Emily': 62, 'Frank': 41}

Install new packages

pip install packages

python -m pip install numpy
import numpy as np ## test if the package has been installed in python
python3 -m pip install numpy==1.23 ## specifying a package version
python3.9 -m pip install --upgrade numpy ## upgrade a package
pip install numpy --user ## if you are not a admin
python -m pip install numpy
>>> import numpy as np ## test if the package has been installed in python
python3 -m pip install numpy==1.23 ## specifying a package version
python3.9 -m pip install --upgrade numpy ## upgrade a package
pip install numpy --user ## if you are not a admin
py -3 -m pip install numpy
>>> import numpy as np ## test if the package has been installed in python
py -3 -m pip install numpy==1.23 ## specifying a package version
py -3 -m pip install --upgrade numpy ## upgrade a package
py -3 -m pip install numpy --user ## if you are not a admin

conda install packages

conda install numpy
conda install numpy=1.16
conda list --name numpy conda ## check current installed version
conda update numpy

How to prepare your own package, and make it installable using pip

Python environment

## source ~/opt/miniconda3/bin/activate ## need this for macOS Catalina or later
conda create -n myenv
## conda create -n myenv python=3.9 ## create an environment with a specific Python version.
conda activate myenv ## activate the environment
conda info --envs ## list all environment
conda install -n myenv scipy=0.17.3
python ## open python with this environment
conda deactivate

Python environment (using pip)

Reference