Welcome to R for Biologists Workshop!

Workflow

Flow Controls

Flow controls add efficiency to your code, making it easier to read and saving you time overall

IF statements

If a condition is TRUE then the code is performed, but if the condition is FALSE then nothing occurs

This can take the form of either a numeric or a logical vector

Numeric

x = 42

x > 0
## [1] TRUE
if(x>0) {
  print ("Positive number")
}
## [1] "Positive number"
x = -42

if (x>0) {
  print("Positive number")
}

Logical

x = 3

x == 3
## [1] TRUE
if (x == 3){
  print ("X is equal to three")
}
## [1] "X is equal to three"
if (x != 3) {
  print ("X is not equal to three")
}

Else Statements

else is optional and is only evaluated if conditions to are FALSE

Numerical

x = 42

if (x > 0) {
  print("Positive number")
} else {
  print ("Negative number")
}
## [1] "Positive number"
y = -42

if (y > 0) {
  print("Positive number")
} else {
  print ("Negative number")
}
## [1] "Negative number"

Logical condition

x = 42
if (x==3){
  print ("X is equal to three")
} else {
  print ("X does not equal to three")
}
## [1] "X does not equal to three"

To get even more control from your block of code, you can use else if controls…

Else If

If you need more conditions to execute your code, then you can utilize the feature of else if flow control

x = 0

if (x==3){
  print ("X is equal to three")
} else if (x == 0){
  print ("X is equal to zero")
} else {
  print ("I don't know what X is")
}
## [1] "X is equal to zero"

Loops

Loops are used in programming to repeat a specific block of code. These include For loops and While loops.

For loops

For loops iterate across a sequence of values, repeatedly running code for each value in a list or vector.

Lets say that we want to print out each element in the vector numbers.You would have to copy and paste the same code four times in order to get the results that you want.

numbers <- c(1,2,3,4,6)

print(numbers[1])
## [1] 1
print(numbers[2])
## [1] 2
print(numbers[3])
## [1] 3
print(numbers[4])
## [1] 4

Whereas using the ‘for loops’ you can do the same thing but with much less effort.

for (var in numbers) {
  print (var)
  }
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 6

You can utilize index within a for loop function as well.

for (var in 1:length(numbers)){
  print (numbers[var])
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 6

While loops

This type of loop continues to repeat until a specific condition is met and the condition evaluates to FALSE

x <- 1

while (x<6){
  print (paste("x is equal to", x))
  
  x <-  x + 1
}
## [1] "x is equal to 1"
## [1] "x is equal to 2"
## [1] "x is equal to 3"
## [1] "x is equal to 4"
## [1] "x is equal to 5"

Notice how in the above code I made sure to correct x so that eventually x will be 6 or greater, whereby the while condition will return FALSE and end. If I didn’t do that, the while function would run forever.

Break and Next statements

Break Statements

Break statements are used to terminate the loop at any chosen iteration.

You can use them in both if statements and for loops

numbers <- c(1,2,4,6)

for (var in numbers){
  if (var == 4){
    print (paste("The variable 4 should not be there, exiting"))
    break
  }
  print(paste("Values are : ", var))
}
## [1] "Values are :  1"
## [1] "Values are :  2"
## [1] "The variable 4 should not be there, exiting"

This immediately stops the function and it does not continue. However, if it does not encounter the break condition, then the code will continue through.

numbers2 <- c(1,3,5,6)

for (var in numbers2){
  if (var == 4){
    print (paste("The variable 4 should not be there, exiting"))
    break
  }
  print(paste("Values are : ", var))
}
## [1] "Values are :  1"
## [1] "Values are :  3"
## [1] "Values are :  5"
## [1] "Values are :  6"

Next Statements

But what if we don’t want to stop the code completely? We just want to skip over a part if it doesn’t match our conditions? Thats where ’Next" statements come in.

numbers <- c(1, 2, 4, 6)

for (var in numbers) {
  if (var ==4) {
    print (paste ("The variable 4 should not be there"))
    next
  }
  print (paste("Values are: ", var))
}
## [1] "Values are:  1"
## [1] "Values are:  2"
## [1] "The variable 4 should not be there"
## [1] "Values are:  6"

Challenge Question 1

What does the following give you?

numbers <- c(1, 2, 4, 6)

for (var in numbers) {
  if (var ==4) {
    print (paste ("The variable 4 should not be there"))
    next
    print (paste("Values are: ", var))
  }
}

Answer:

## [1] "The variable 4 should not be there"

Functions

Functions take an input (argument) and produces an output. R has many functions available to do bioinformatics work.

numbers <-c(1, 2, 4, 6)

print (numbers)
## [1] 1 2 4 6
str(numbers)
##  num [1:4] 1 2 4 6
sum (numbers)
## [1] 13
mean (numbers)
## [1] 3.25

Read and write csv functions

These types of functions allow you to manipulate external files into or out of the R environment.

The read.csv function reads in an external table into your R environment

Data.table <- read.csv("Bioinformatics.csv")

The write.csv function writes a data frame or other object into a table that can then be opened with excel or another text editor

my.df <- data.frame(x = 1:5, y = 3:7)

write.csv (my.df, "Bioinformatics_data.csv")

Challenge Question 2

In our previous .csv file that we had, the rows all matched together. But what happens when you read in a file that does not have matching rows/columns?

C_Question2 <- read.csv("ChallengeQuestion2.csv")

Answer:

##    ï..Bioinfo Numbers
## 1           1       2
## 2           2       3
## 3           3       4
## 4           3       5
## 5           4       6
## 6           5       6
## 7           6       5
## 8           5       5
## 9           4       6
## 10          6       5
## 11         NA       6
## 12         NA       6
## 13         NA       7

Make your own function

You can also utilize the full power of functions in R by personalizing them to your specific problem. General functions can make your code more clear, and can be easier to maintain that specific code. These can be functions assigned to variables.

Function example

Square_It <- function (x) {
  y <-  x^2
  print(paste("The Square of", x, "is", y))
}

Square_It(5)
## [1] "The Square of 5 is 25"
Square_It(42)
## [1] "The Square of 42 is 1764"

Apply functions

Iterates the functions over elements in a list or a vector (lapply) or over a dataframe (apply). These functions are very similar to a for loop, but can be done in 1 line of code.

3 types of apply functions

  • apply
  • lapply
  • sapply

Apply

Lets say that we have our dataframe:

##    x y
## 1  2 1
## 2  5 2
## 3 10 3
## 4  2 4
## 5  3 5

and we want to calculate the mean of each individual row in that dataframe. Lets try it with a for loop.

for (var in 1:nrow(my.df2)) {
  mymean= mean(as.numeric(my.df2[var,]))
  print(mymean)
}
## [1] 1.5
## [1] 3.5
## [1] 6.5
## [1] 3
## [1] 4

Lets try it with apply instead

apply(my.df2, 1,  mean)
## [1] 1.5 3.5 6.5 3.0 4.0

lapply

lapply works on vectors or lists, and outputs the results as a list.

x <- sample(1:100, size = 10)
y <- sample(1:100, size = 10)
z <-  sample (1:100, size = 10)

lis <- list (x, y, z)

lis_min <- lapply(lis, min)

print(lis_min)
## [[1]]
## [1] 2
## 
## [[2]]
## [1] 2
## 
## [[3]]
## [1] 6
str(lis_min)
## List of 3
##  $ : int 2
##  $ : int 2
##  $ : int 6

sapply

As opposed to lapply, sapply will try to simplify the output of lapply()

Ths will try to output a simple array rather than a list.

x <- sample(1:100, size = 10)
y <- sample(1:100, size = 10)
z <-  sample (1:100, size = 10)

lis <- list (x, y, z)

lis_min <- sapply(lis, min)

print (lis_min)
## [1]  2 19  2
str(lis_min)
##  int [1:3] 2 19 2

Which function

In R, the which() function gives you the position of elements

geneIDs=read.csv("gene_id_to_symbol.csv")

Ensemble = c("ENSG00000121410", "ENSG00000175899","ENSG00000256069", "ENSG00000171428", "ENSG00000156006",
             "ENSG00000196136", "ENSG00000114771")
gene_symbol= c("A1BG", "A2M", "A2MP1","NAT1", "NAT2", "SERPINA3", "AADAC" )
entrez=c(1, 2, 3, 9, 10, 12, 13)

mygenes <- data.frame(entrez= entrez, gene_symbol= gene_symbol, Ensemble = Ensemble)

mygenes
##   entrez gene_symbol        Ensemble
## 1      1        A1BG ENSG00000121410
## 2      2         A2M ENSG00000175899
## 3      3       A2MP1 ENSG00000256069
## 4      9        NAT1 ENSG00000171428
## 5     10        NAT2 ENSG00000156006
## 6     12    SERPINA3 ENSG00000196136
## 7     13       AADAC ENSG00000114771
my_which_function <- which(mygenes$Ensemble == "ENSG00000256069")

my_which_function
## [1] 3

How can the which function be powerful? Because, for example, you can use the output of the which function to return all the values in the row of your search.

mygenessearch <- mygenes[my_which_function,]

mygenessearch
##   entrez gene_symbol        Ensemble
## 3      3       A2MP1 ENSG00000256069

The End!

Homework: Practice problems, and datacamp