Set Up

library(reticulate) # to use python in RStudio
library(tidyverse) # data wrangling and plotting with R

R code chunks are in light pink, while python in light blue.

Highlight


  • For loops are for when we have known number or sequence of iterations we would like to perform. We could iterate through strings, lists, tuples, dictionaries, or within a range.

  • While loops are for when we want to repeat a process until certain threshold is met.

  • We are more likely to use for loops than while loops in practice. And we can always alter interations of a for loop using conditional statements.

  • Small tips

    • Some of the repetitive tasks with lists and dictionaries can be done using comprehension concisely.
    • Talking about conciseness, this reference about inplace operations in R might of some interests.

For loops

For loop with strings

statement = 'I can work in '

for i in statement: # for each character in the string
  print(i)
## I
##  
## c
## a
## n
##  
## w
## o
## r
## k
##  
## i
## n
## 

For loop with lists

language = ['R','Python','Julia']

for i in language: # for each item in the list
  print(f'{statement}{i}!')
  
## I can work in R!
## I can work in Python!
## I can work in Julia!

We can create a new list that contains the concatenated items as follows using for loop.

ml=[]
for i in language:
  ml.append(statement+i)
ml
## ['I can work in R', 'I can work in Python', 'I can work in Julia']

A note on list comprehension

Worth noting that the same task can be done using list comprehension in one line, which is really concise and convenient!

ml = [statement + i for i in language]
ml
## ['I can work in R', 'I can work in Python', 'I can work in Julia']

We can easily use comprehension with dictionaries too

md = {x : x**2 for x in range(1,10)}
md
## {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

We can also add conditions in comprehension. In the following example, we limit x to be divisible by both 2 and 3.

md = {x: x**2 for x in range(1,20) if not (x%2 or x%3)}
md
## {6: 36, 12: 144, 18: 324}

enumerate with lists

Normally for lists, we are mainly interested in its items. But sometimes if we are also interested in the index, enumerate() function can be used.

ml = [1,2,3,4,5]

for idx, item in enumerate(ml):
  print(f'No. {idx} item: ', item)
## No. 0 item:  1
## No. 1 item:  2
## No. 2 item:  3
## No. 3 item:  4
## No. 4 item:  5

For loop with tuples

mt = (0,1,2,3,4,5)

mySUM = 0

for i in mt: # for each item in the tuple
  mySUM += i # concise way of saying mySUM = mySUM + i
  print(mySUM)
## 0
## 1
## 3
## 6
## 10
## 15

For loop with dictionaries

For loop with dictionaries is a bit different because dictionaries have key: value pairs. When iterating with a dictionary, we need to decide what we want, the key, the value or both.

md = {'FirstName': 'John', 'LastName': 'Doe', 'Age': 35}

for k, v in md.items(): # items() method extracts both keys and values
  print(f'{k}: {v}')
  
## FirstName: John
## LastName: Doe
## Age: 35
for k in md.keys(): # keys() method extracts keys only
  print(f'The key is {k}')
## The key is FirstName
## The key is LastName
## The key is Age

In a dictionary, we could have more complex values, say lists, tuples or dataframes.

md2 = {'10s': (10,11,12),'20s': (20,21,22)}

In the above dictionary, we have tuples as values. And we can iterate through each keys and then items in each tuple too.

for k, t in md2.items(): # iterate through each key:value pair
  print(f'Shwoing {k}: ', end = ' ') # space rather than new line at the end
  for i in t: # iterate through each tuple
    print(i, end = ' ') 
  print() # add a new line
  print(30*'-') # add a dashed line
## Shwoing 10s:  10 11 12 
## ------------------------------
## Shwoing 20s:  20 21 22 
## ------------------------------

For loop in R

For loops in R are quite similar to those in Python.

mv <- c(0:5) # create a vector

mySUM <- 0

for (i in mv) { # for each item in the vector
  mySUM = mySUM + i # see note below about modifying objects in place 
  print(mySUM)
}
## [1] 0
## [1] 1
## [1] 3
## [1] 6
## [1] 10
## [1] 15

Also for anyone who is interested, we could also do += sort of operation in R with the inplace package. Here is how

For loop in range()

In addition to iterating through strings, lists, tuples and dicctionaries as demonstrated above, a for loop could also iterate through a range. Follows pls see how this can be used to replicate the example with a tuple above. Note that when constructing a range object, the starting integer is included, while the ending integer is not. Therefore, range(6) in the following example includes a sequence from 0 to 5.

mySUM=0
for i in range(6): # range: 0 to 5 by 1
  mySUM += i
  print('total: ', mySUM)
## total:  0
## total:  1
## total:  3
## total:  6
## total:  10
## total:  15

We can define a range object by specifying the staring integer, ending integer and the interval.

  
for i in range(2,11,2): # range: 2 to 10 by 2
  print('index: ', i)
## index:  2
## index:  4
## index:  6
## index:  8
## index:  10

For a more interesting and complex example of for loop in range(), please click here.

While loops

The while loop is helpful when we want to continue a process until certain threshold is met. For example, say we have an infectious disease with R0 = 12, let’s use the while loop to demo how it can grow to over 10K cases.

# say we have only 1 case at day0
Total = 1 
Days = 0
# the while loop:
while Total < 10000:
  Total *= 12 # r0 = 12  
  Days += 1
  print(f'Day{Days}: {Total} cases')
## Day1: 12 cases
## Day2: 144 cases
## Day3: 1728 cases
## Day4: 20736 cases
print('10,000 cases reached!')
## 10,000 cases reached!

Modify interations

Commands are available in Python for us to break out of a loop or modify iterations. As follows please see examples with two common commands for such purposes, else and break.

else

* for loops: when the sequence has been exhausted  
* while loops: when the while condition has become false
for i in range(1,4,1): #1,2,3
  print(f'i={i}')
else:
  print(f'else executed when i={i}')
## i=1
## i=2
## i=3
## else executed when i=3
mySum = 1000000
while mySum > 100:
  mySum /=10
  print(f'mySum is {mySum}')
else:
  print(f'mySum is {mySum} and the minumum has been reached')
## mySum is 100000.0
## mySum is 10000.0
## mySum is 1000.0
## mySum is 100.0
## mySum is 100.0 and the minumum has been reached

break

* normally used in nested loops
* to terminate the closest enclosing loop
for i in range(1,8,3): #1,4,7
  sum_j = 0
  for j in range(4): 
    sum_j += j
    if i < sum_j:
        break
    print(f'i={i} is no less than the sum of j={sum_j}')
    print('inner loop iteration')
  print('//break out of the inner loop//\n') 
    
## i=1 is no less than the sum of j=0
## inner loop iteration
## i=1 is no less than the sum of j=1
## inner loop iteration
## //break out of the inner loop//
## 
## i=4 is no less than the sum of j=0
## inner loop iteration
## i=4 is no less than the sum of j=1
## inner loop iteration
## i=4 is no less than the sum of j=3
## inner loop iteration
## //break out of the inner loop//
## 
## i=7 is no less than the sum of j=0
## inner loop iteration
## i=7 is no less than the sum of j=1
## inner loop iteration
## i=7 is no less than the sum of j=3
## inner loop iteration
## i=7 is no less than the sum of j=6
## inner loop iteration
## //break out of the inner loop//

Of course, we can use break and else together. The following example uses an outer loop plus an inner loop to identify prime numbers from 1 to 25. The else clause is executed if, and only if, the inner loop terminates normally. In other words, if the inner loop invokes break, which means a divisor was found, the else clause will not be executed. The example is posted by Dave Wade-Stein in this thread on Quora entitled What are the downsides of the python programming language?

for num in range(2, 26):
  for check in range (2, num):
    if num % check == 0:
      break
  else:
    print(num, 'is prime')
## 2 is prime
## 3 is prime
## 5 is prime
## 7 is prime
## 11 is prime
## 13 is prime
## 17 is prime
## 19 is prime
## 23 is prime

Pass

We could also use pass as a placeholder when we are not sure what to do under certain condition yet.

for i in range(1000, 1500):
  if not i%67: # find and print the first integer that can be divided by 67
    print(i)
    break
  else:
    pass # pass
## 1005