Introduction to R, Session 1

LMS Bioinformatics

April 2022

Overview

Materials

Materials - Presentations, source code and practicals.

Once the zip file in unarchived. All presentations as HTML slides and pages, their R code and HTML practical sheets will be available in the directories underneath.

Set the Working directory

Before running any of the code in the practicals or slides we need to set the working directory to the folder we unarchived.

You may navigate to the unarchived Reproducible-R folder in the Rstudio menu

Session -> Set Working Directory -> Choose Directory

or in the console.

setwd("/PathToMyDownload/Reproducible-R")
# e.g. setwd("~/Downloads/Reproducible-R")

Background to R

What is R?

R is a scripting language and environment for statistical computing.

Developed by Robert Gentleman and Ross Ihaka.

Inheriting much from S (Bell labs).

Why should you use R ?

R comes with excellent “out-of-the-box” statistical and plotting capabilities.

R provides access to 1000s of packages (CRAN/MRAN/R-forge) which extend the basic functionality of R while maintaining high quality documentation.

In particular, Robert Gentleman developed the Bioconductor project where 100’s of packages are directly related to computational biology and analysis of associated high-throughput experiments.

path

How to get R

Freely available from R-project website.

RStudio provides an integrated development environment (IDE) which is freely available from RStudio site

We will be using RStudio and R already installed on your machines.

path

path

A quick tour of RStudio

path

Data types in R

Simple Calculations

> 3+1
## [1] 4
> 2*2
## [1] 4
> sqrt(25)-1
## [1] 4

Functions

The sqrt(25) demonstrates the use of functions in R. A function performs a complex operation on it’s arguments and returns the result.

In R, arguments are provided to a function within the parenthesis – ( ) – that follows the function name. So sqrt(ARGUMENT) will provide the square root of the value of ARGUMENT.

Other examples of functions include min(), sum(), max().

Note multiple arguments are separated by a comma.

min(2,4,6)
## [1] 2
sum(2,4,6)
## [1] 12
max(2,4,6)
## [1] 6

Using functions

R has many useful functions “built in” and ready to use as soon as R is loaded.

An incomplete, illustrative list can be seen here

In addition to R standard functions, additional functionality can be loaded into R using libraries. These include specialised tools for areas such as sequence alignment, read counting etc.

If you need to see how a function works try ? in front of the function name.

?sqrt

Using functions (Arguments have names and order)

With functions such as min() and sqrt(), the arguments to be provided are obvious and the order of these arguments doesnt matter.

min(5,4,6)
## [1] 4
min(6,4,5)
## [1] 4

Many functions however have an order to their arguments. Try and look at the arguments for the dir() function using ?dir.

?dir

Using functions (Setting names for arguments)

Often we know the names of arguments but not necessarily their order. In cases where we want to be sure we specify the right argument, we provide names for the arguments used.

dir()
dir(full.names=T)

This also means we don’t have to copy out all the defaults for arguments preceeding it.

dir(full.names=T)
# Is equivalent to...
dir(".",NULL,FALSE,T)

Variable

As with other programming languages and even graphical calculators, R makes use of variables.

A variable stores a value as a letter or word.

In R, we make use of the assignment operator <-

x <- 10

Now x holds the value of 10

x
## [1] 10
x
## [1] 10

Variables can be altered in place

x <- 20
x
## [1] 20

Variables can be used just as the values they contain.

x + sqrt(25)
## [1] 25

Variables can be used to create new variables

y <- x + sqrt(25)
y
## [1] 25

Vectors

In R the most basic variable or data type is a vector. A vector is an ordered collection of values. The x and y variables we have previously assigned are examples of a vector of length 1.

x
## [1] 20
length(x)
## [1] 1

Vectors - Creating vectors

To create a multiple value vector we use the function c() to combine the supplied arguments into one vector.

x <- c(1,2,3,4,5,6,7,8,9,10)
x
##  [1]  1  2  3  4  5  6  7  8  9 10
length(x)
## [1] 10

Vectors of continuous stretches of values can be created by the shortcut - :

y <- 6:10
y
## [1]  6  7  8  9 10

Other useful function to create stretchs of numeric vectors are seq() and rep(). The seq() function creates a sequence of numeric values from a specified start and end value, incrementing by a user defined amount. The rep() function repeats a variable a user-defined number of times.

seq(from=1,to=5,by=2)
## [1] 1 3 5
rep(c(1,5,10),3)
## [1]  1  5 10  1  5 10  1  5 10

Vectors - Indexing

Square brackets [] identify the position within a vector (the index). These indices can be used to extract relevant values from vectors.

x
##  [1]  1  2  3  4  5  6  7  8  9 10
x[1]
## [1] 1
x[8]
## [1] 8

Indices can be used to extract values from multiple positions within a vector.

x[c(1,6)]
## [1] 1 6

Negative indices can be used to extract all positions except that specified

x[-5]
## [1]  1  2  3  4  6  7  8  9 10

Vectors - Indexing and replacement

We can use indices to modify a specific position in a vector

x
##  [1]  1  2  3  4  5  6  7  8  9 10
x[5] <- -5
x
##  [1]  1  2  3  4 -5  6  7  8  9 10

Indices can be specified using other vectors.

y
## [1]  6  7  8  9 10
x[y] <- 0
x
##  [1]  1  2  3  4 -5  0  0  0  0  0

Remember!

Square brackets [] for indexing

x[1]
## [1] 1

Parentheses () for function argments.

sqrt(4)
## [1] 2

Vectors - Arithmetic operations

Vectors in R can be used in arithmetic operations as seen with variables earlier. When a standard arithmetic operation is applied to vector, the operation is applied to each position in a vector.

x <- c(1,2,3,4,5,6,7,8,9,10)
x
##  [1]  1  2  3  4  5  6  7  8  9 10
y <- x*2
y
##  [1]  2  4  6  8 10 12 14 16 18 20

Multiple vectors can be used within arithmetic operations.

x+y
##  [1]  3  6  9 12 15 18 21 24 27 30

Vectors - Character vectors

So far we have only looked at numeric vectors or variables.

In R we can also create character vectors again using c() function. These vectors can be indexed just the same.

y <- c("ICTEM","CommonWealth","Wolfson")
y[2]
## [1] "CommonWealth"

Character vectors can be used to assign names to other vectors.

x <- c(1:3)
names(x) <- y
x
##        ICTEM CommonWealth      Wolfson 
##            1            2            3
    These named vectors maybe indexed by a position's "name".
x[c("ICTEM","Wolfson")]
##   ICTEM Wolfson 
##       1       3

Index names missing from vectors will return special value “NA”

x[c("Strand")]
## <NA> 
##   NA

A note on NA values

In R, like many languages, when a value in a variable is missing, the value is assigned a NA value.

Similarly, when a calculation can not be perfomed, R will input a NaN value.

NA values allow for R to handle missing data correctly but requires different handling than standard numeric or character values. We will illustrate an example handling NA values later.

Vectors - The unique() function

The unique() function can be used to retrieve all unique values from a vector.

geneList <- c("Gene1","Gene2","Gene3","Gene4","Gene5","Gene1","Gene3")
unique(geneList)
## [1] "Gene1" "Gene2" "Gene3" "Gene4" "Gene5"

Vectors. Logical vectors

Logical vectors are a class of vector made up of TRUE/T or FALSE/F boolean values.

z <- c(T,F,T,F,T,F,T,F,T,F) 
# z <-  c(TRUE,FALSE,TRUE,FALSE,TRUE,FALSE,TRUE,FALSE,TRUE,FALSE) 
z
##  [1]  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE

Logical vectors can be used like an index to specify postions in a vector. TRUE values will return the corresponding position in the vector being indexed.

x <- 1:10
x[z]
## [1] 1 3 5 7 9

Vectors - The %in% operator

A common task in R is to subset one vector by the values in another vector.

The %in% operator in the context A %in% B creates a logical vector of whether values in A matches any values in of B.

This can be then used to subset the values within one character vector by a those in a second.

geneList <- c("Gene1","Gene2","Gene3","Gene4","Gene5","Gene1","Gene3")
secondGeneList <- c("Gene5","Gene3")
logical_index <- geneList %in% secondGeneList
logical_index
## [1] FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE
geneList[logical_index]
## [1] "Gene3" "Gene5" "Gene3"

Vectors - Logical vectors from operators

Vectors may be evaluated to produce logical vectors. This can be very useful when using a logical to index.

Common examples are:

x <- 1:10
x > 5
##  [1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
x[x > 5]
## [1]  6  7  8  9 10

Vectors - Combining logical vectors

Logical vectors can be used in combination in order to index vectors. To combine logical vectors we can use some common R operators.

x <- 1:10
!x > 4
##  [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
x > 4 & x < 7
##  [1] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE
x > 4 | x < 7
##  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

Such combinations can allow for complex selection of a vector’s values.

x <- 1:10
x
##  [1]  1  2  3  4  5  6  7  8  9 10
x[x > 4 & x < 7]
## [1] 5 6
x[x > 4 & !x < 7]
## [1]  7  8  9 10

Exercise!

Exercise on vectors can be found here

Answers to exercise

Answers can be found here here

R code for solutions can be found here here

Matrices

Creating matrices

In programs such as Excel, we are used to tables.

All progamming languages have a concept of a table. In R, the most basic table type is a matrix.

A matrix can be created using the matrix() function with the arguments of nrow and ncol specifying the number of rows and columns respectively.

narrowMatrix <- matrix(1:10, nrow=5, ncol=2)
narrowMatrix
##      [,1] [,2]
## [1,]    1    6
## [2,]    2    7
## [3,]    3    8
## [4,]    4    9
## [5,]    5   10
wideMatrix <- matrix(1:10, nrow=2, ncol=5)
wideMatrix
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8   10

By default when creating a matrix using the matrix function, the values fill the matrix by columns. To fill a matrix by rows the byrow argument must be set to TRUE.

wideMatrix <- matrix(1:10, nrow=2, ncol=5)
wideMatrix
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8   10
wideMatrixByRow <- matrix(1:10, nrow=2, ncol=5, byrow=TRUE)
wideMatrixByRow
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    2    3    4    5
## [2,]    6    7    8    9   10

Finding dimensions

To find dimensions of a matrix, the dim() function will provide dimensions as the row then column number while nrow() and ncol() will return just row number and column number respectively.

dim(narrowMatrix)
## [1] 5 2
nrow(narrowMatrix)
## [1] 5
ncol(narrowMatrix)
## [1] 2

Joining vectors and matrices

A matrix can be created from multiple vectors or other matrices.

cbind() can be used to attach data to a matrix as columns.

x <- 1:10
y <- 11:20
z <- 21:22
newMatrix <- cbind(x,y)
newMatrix
##        x  y
##  [1,]  1 11
##  [2,]  2 12
##  [3,]  3 13
##  [4,]  4 14
##  [5,]  5 15
##  [6,]  6 16
##  [7,]  7 17
##  [8,]  8 18
##  [9,]  9 19
## [10,] 10 20

rbind() functions to bind to a matrix as rows.

newerMatrix <- rbind(newMatrix,z)
newerMatrix
##    x  y
##    1 11
##    2 12
##    3 13
##    4 14
##    5 15
##    6 16
##    7 17
##    8 18
##    9 19
##   10 20
## z 21 22

Joining incompatable vectors and matrices

When creating a matrix using cbind() or matrix() from incompatable vectors then the shorter vector is recycled.

recycledMatrix2 <- matrix(1:5,ncol=2,nrow=3)
## Warning in matrix(1:5, ncol = 2, nrow = 3): data length [5] is not a sub-
## multiple or multiple of the number of rows [3]
recycledMatrix2
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    1

For rbind() function, the longer vector is clipped.

recycledMatrix3 <- rbind(recycledMatrix2,c(1:5))
## Warning in rbind(recycledMatrix2, c(1:5)): number of columns of result is not a
## multiple of vector length (arg 2)
recycledMatrix3
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    1
## [4,]    1    2

Column and row names

As we have seen with vectors, matrices can be named. For matrices the naming is done by columns and rows using colnames() and rownames() functions.

namedMatrix <- matrix(1:10,ncol=5,nrow=2)
colnames(namedMatrix) <- paste("Column",1:5,sep="_")
rownames(namedMatrix) <- paste("Row",1:2,sep="_")
namedMatrix
##       Column_1 Column_2 Column_3 Column_4 Column_5
## Row_1        1        3        5        7        9
## Row_2        2        4        6        8       10

Information on matrix names can also be retreived using the same functions.

colnames(namedMatrix)
## [1] "Column_1" "Column_2" "Column_3" "Column_4" "Column_5"
rownames(namedMatrix)
## [1] "Row_1" "Row_2"

Indexing

Selecting and replacing portions of a matrix can be done by indexing using square brackets [] much like for vectors.

When indexing matrices, two values may be provided within the square brackets separated by a comma to retrieve information on a matrix position.

The first value(s) corresponds to row(s) and the second to column(s).

narrowMatrix
##      [,1] [,2]
## [1,]    1    6
## [2,]    2    7
## [3,]    3    8
## [4,]    4    9
## [5,]    5   10

Value of first column, second row

narrowMatrix[2,1]
## [1] 2

Similarly, whole rows or columns can be extracted. Single rows and columns will return a vector. When multiple columns or row indices are specified, a matrix is returned.

Values of second column (row index is empty!)

narrowMatrix[,2]
## [1]  6  7  8  9 10

Values of third row (column index is empty!)

narrowMatrix[3,]
## [1] 3 8

Values of second and third row (column index is empty!)

narrowMatrix[c(2,3),]
##      [,1] [,2]
## [1,]    2    7
## [2,]    3    8

Indexing by name

As with vectors, names can be used for indexing when present

colnames(narrowMatrix) <- paste("Column",1:2,sep="_")
rownames(narrowMatrix) <- paste("Row",1:5,sep="_")
narrowMatrix[,"Column_1"]
## Row_1 Row_2 Row_3 Row_4 Row_5 
##     1     2     3     4     5
narrowMatrix["Row_1",]
## Column_1 Column_2 
##        1        6
narrowMatrix["Row_1","Column_1"]
## [1] 1

Advanced indexing

As with vectors, matrices can be subset by logical vectors

narrowMatrix
##       Column_1 Column_2
## Row_1        1        6
## Row_2        2        7
## Row_3        3        8
## Row_4        4        9
## Row_5        5       10
narrowMatrix[,1]
## Row_1 Row_2 Row_3 Row_4 Row_5 
##     1     2     3     4     5
narrowMatrix[,1] < 5
## Row_1 Row_2 Row_3 Row_4 Row_5 
##  TRUE  TRUE  TRUE  TRUE FALSE
narrowMatrix[narrowMatrix[,1] < 5,]
##       Column_1 Column_2
## Row_1        1        6
## Row_2        2        7
## Row_3        3        8
## Row_4        4        9

Arithmetic operations

As with vectors, matrices can have arithmetic operations applied to cells,rows, columns or the whole matrix

narrowMatrix
##       Column_1 Column_2
## Row_1        1        6
## Row_2        2        7
## Row_3        3        8
## Row_4        4        9
## Row_5        5       10
narrowMatrix[1,1]+2
## [1] 3
narrowMatrix[1,]+2
## Column_1 Column_2 
##        3        8
mean(narrowMatrix)
## [1] 5.5

Replacement

As with vectors, matrices can have their elements replaced

narrowMatrix
##       Column_1 Column_2
## Row_1        1        6
## Row_2        2        7
## Row_3        3        8
## Row_4        4        9
## Row_5        5       10
narrowMatrix[1,1] <- 10
narrowMatrix[,2] <- 1
narrowMatrix
##       Column_1 Column_2
## Row_1       10        1
## Row_2        2        1
## Row_3        3        1
## Row_4        4        1
## Row_5        5        1

Matrices can contain only one data type

Matrices must be all one type (i.e. numeric or character).

Here replacing one value with character will turn numeric matrix to character matrix.

narrowMatrix[,2] *2
## Row_1 Row_2 Row_3 Row_4 Row_5 
##     2     2     2     2     2
narrowMatrix[1,1] <- "Not_A_Number"
narrowMatrix
##       Column_1       Column_2
## Row_1 "Not_A_Number" "1"     
## Row_2 "2"            "1"     
## Row_3 "3"            "1"     
## Row_4 "4"            "1"     
## Row_5 "5"            "1"
narrowMatrix[,2] *2
## Error in narrowMatrix[, 2] * 2: non-numeric argument to binary operator

Exercise

Exercise on matrices can be found here

Answers to exercise

Answers can be found here here

R code for solutions can be found here

Factors

Creating factors

A special case of a vector is a factor.

Factors are used to store data which may be grouped in categories (categorical data). Specifying data as categorical allows R to properly handle the data and make use of functions specific to categorical data.

To create a factor from a vector we use the factor() function. Note that the factor now has an additional component called “levels” which identifies all categories within the vector.

vectorExample <- c("male","female","female","female")
factorExample <- factor(vectorExample)
factorExample
## [1] male   female female female
## Levels: female male
levels(factorExample)
## [1] "female" "male"

Summary() function

An example of the use of levels can be seen from applying the summary() function to the vector and factor examples

summary(vectorExample)
##    Length     Class      Mode 
##         4 character character
summary(factorExample)
## female   male 
##      3      1

Display order of levels

In our factor example, the levels have been displayed in an alphabetical order. To adjust the display order of levels in a factor, we can supply the desired display order to levels argument in the factor() function call.

factorExample <- factor(vectorExample,levels=c("male","female"))
factorExample
## [1] male   female female female
## Levels: male female
summary(factorExample)
##   male female 
##      1      3

Nominal factors

In some cases there is no natural order to the categories such that one category is greater than the other (nominal data). In this case we can see that R is gender neutral.

factorExample <- factor(vectorExample,levels=c("male","female"))
factorExample[1] < factorExample[2]
## Warning in Ops.factor(factorExample[1], factorExample[2]): '<' not meaningful
## for factors
## [1] NA

Ordinal factors

In other cases there will be a natural ordering to the categories (ordinal data). A factor can be specified to be ordered using the ordered argument in combination with specified levels argument.

factorExample <- factor(c("small","big","big","small"),ordered=TRUE,levels=c("small","big"))
factorExample
## [1] small big   big   small
## Levels: small < big
factorExample[1] < factorExample[2]
## [1] TRUE

Replacement

Unlike vectors, replacing elements within a factor isn’t so easy. While replacing one element with an established level is possible, replacing with a novel element will result in a warning.

factorExample <- factor(c("small","big","big","small"))
factorExample[1] <- c("big")
factorExample
## [1] big   big   big   small
## Levels: big small
factorExample[1] <- c("huge")
## Warning in `[<-.factor`(`*tmp*`, 1, value = "huge"): invalid factor level, NA
## generated
factorExample
## [1] <NA>  big   big   small
## Levels: big small

To add a new level we can use the levels argument.

levels(factorExample) <- c("big","small","huge")
factorExample[1] <- c("huge")
factorExample
## [1] huge  big   big   small
## Levels: big small huge

Data frames

We saw that with matrices you can only have one type of data. We tried to create a matrix with a character element and the entire matrix became a character.

In practice, we would want to have a table which is a mixture of types (e.g a table with sample names (character), sample type (factor) and survival time (numeric))

Creating Data Frames

In R, we make use of the data frame object which allows us to store tables with columns of different data types. To create a data frame we can simply use the data.frame() function.

patientName <- c("patient1","patient2","patient3","patient4")
patientType <- factor(rep(c("male","female"),2))
survivalTime <- c(1,30,2,20)
dfExample <- data.frame(Name=patientName, Type=patientType,Survival_Time=survivalTime)
dfExample
##       Name   Type Survival_Time
## 1 patient1   male             1
## 2 patient2 female            30
## 3 patient3   male             2
## 4 patient4 female            20

Indexing and replacement

Using []

Data frames may be indexed just as matrices.

dfExample
##       Name   Type Survival_Time
## 1 patient1   male             1
## 2 patient2 female            30
## 3 patient3   male             2
## 4 patient4 female            20
dfExample[dfExample[,"Survival_Time"] > 10,]
##       Name   Type Survival_Time
## 2 patient2 female            30
## 4 patient4 female            20

Using $ to specify columns

Unlike matrices, it is possible to index a column by using the $ symbol.

dfExample <- data.frame(Name=patientName,Type=patientType,Survival_Time=survivalTime)
dfExample$Survival_Time
## [1]  1 30  2 20
dfExample[dfExample$Survival_Time < 10,]
##       Name Type Survival_Time
## 1 patient1 male             1
## 3 patient3 male             2

Using the $ allows for R to autocomplete your selection and so can speed up coding.

dfExample$Surv
## [1]  1 30  2 20

But this will not work..

dfExample[,"Surv"]

Creating new columns with $

The $ operator also allows for the creation of new columns for a data frame on the fly.

dfExample
##       Name   Type Survival_Time
## 1 patient1   male             1
## 2 patient2 female            30
## 3 patient3   male             2
## 4 patient4 female            20
dfExample$newColumn <- rep("newData",nrow(dfExample))
dfExample
##       Name   Type Survival_Time newColumn
## 1 patient1   male             1   newData
## 2 patient2 female            30   newData
## 3 patient3   male             2   newData
## 4 patient4 female            20   newData

Indexing and replacement

Certain columns can not be replaced in data frames. Numeric columns may have their values replaced but columns with character values may not by default. This occurs because character vectors are treated as factors by default.

dfExample[dfExample[,"Survival_Time"] < 10,"Survival_Time"] <- 0
dfExample
##       Name   Type Survival_Time newColumn
## 1 patient1   male             0   newData
## 2 patient2 female            30   newData
## 3 patient3   male             0   newData
## 4 patient4 female            20   newData
dfExample[dfExample[,"Survival_Time"] < 10,"Name"] <- "patientX"
dfExample
##       Name   Type Survival_Time newColumn
## 1 patientX   male             0   newData
## 2 patient2 female            30   newData
## 3 patientX   male             0   newData
## 4 patient4 female            20   newData

Factors in data frames

It is possible to update factors in data frames just as with standard factors.

dfExample <- data.frame(Name=patientName,Type=patientType,Survival_Time=survivalTime)

levels(dfExample[,"Name"]) <- c(levels(dfExample[,"Name"]) , "patientX")
dfExample[dfExample[,"Survival_Time"] < 10,"Name"] <- "patientX"
dfExample
##       Name   Type Survival_Time
## 1 patientX   male             1
## 2 patient2 female            30
## 3 patientX   male             2
## 4 patient4 female            20

Creating data frames without factors

If you wish to avoid using factors in data frames then the stringsAsFactors argument to data.frame() function should be set to FALSE

dfExample <- data.frame(Name=patientName,
                        Type=patientType,
                        Survival_Time=survivalTime,
                        stringsAsFactors = F)


dfExample[dfExample[,"Survival_Time"] < 10,"Name"] <- "patientX"
dfExample
##       Name   Type Survival_Time
## 1 patientX   male             1
## 2 patient2 female            30
## 3 patientX   male             2
## 4 patient4 female            20

Ordering with order() function

A useful function in R is order()

For numeric vectors, order() by default returns the indices of a vector in that vector’s increasing order. This behaviour can be altered by using the “decreasing” argument passed to order.

testOrder <- c(2,1,3)
testOrder
## [1] 2 1 3
testOrder[order(testOrder)]
## [1] 1 2 3
testOrder[order(testOrder,decreasing=T)]
## [1] 3 2 1

Ordering with NA values

When a vector contains NA values, these NA values will, by default, be placed last in ordering indices. This can be controlled by na.last argument.

testOrder <- c(2,1,NA,3)
testOrder[order(testOrder,decreasing=T,na.last=T)]
## [1]  3  2  1 NA
testOrder[order(testOrder,decreasing=T,na.last=F)]
## [1] NA  3  2  1

Ordering data frames

Since the order argument returns an index of intended order for a vector, we can use the order() function to order data frames by certain columns

dfExample
##       Name   Type Survival_Time
## 1 patientX   male             1
## 2 patient2 female            30
## 3 patientX   male             2
## 4 patient4 female            20
dfExample[order(dfExample$Surv, decreasing=T),]
##       Name   Type Survival_Time
## 2 patient2 female            30
## 4 patient4 female            20
## 3 patientX   male             2
## 1 patientX   male             1

We can also use order to arrange multiple columns in a data frame by providing multiple vectors to order() function. Ordering will be performed in order of arguments.

dfExample[order(dfExample$Type,
                dfExample$Survival,
                decreasing=T),]
##       Name   Type Survival_Time
## 3 patientX   male             2
## 1 patientX   male             1
## 2 patient2 female            30
## 4 patient4 female            20

Merging data frames

A common operation is to join two data frames by a column of common values.

dfExample <- data.frame(Name=patientName,
                        Type=patientType,
                        Survival_Time=survivalTime)
dfExample 
##       Name   Type Survival_Time
## 1 patient1   male             1
## 2 patient2 female            30
## 3 patient3   male             2
## 4 patient4 female            20
dfExample2 <- data.frame(Name=patientName[1:3],
                         height=c(6.1,5.1,5.5))
            
dfExample2
##       Name height
## 1 patient1    6.1
## 2 patient2    5.1
## 3 patient3    5.5

Merging data frames with merge()

To do this we can use the merge() function with the data frames as the first two arguments. We can then specify the columns to merge by with the by argument. To keep only data pertaining to values common to both data frames the all argument is set to TRUE.

mergedDF <- merge(dfExample,dfExample2,by=1,all=F)
mergedDF
##       Name   Type Survival_Time height
## 1 patient1   male             1    6.1
## 2 patient2 female            30    5.1
## 3 patient3   male             2    5.5

Time for an exercise

Exercise on data frames can be found here

Answers to exercise

Answers can be found here here

R code solutions can be found here

Lists

Creating lists

Lists are the final data-type we will look at.

In R, lists provide a general container which may hold any data types of unequal lengths as part of its elements. To create a list we can simply use the list() function with arguments specifying the data we wish to include in the list.

firstElement <- c(1,2,3,4)
secondElement <- matrix(1:10,nrow=2,ncol=5)
thirdElement <- data.frame(colOne=c(1,2,4,5),colTwo=c("One","Two","Three","Four"))
myList <- list(firstElement,secondElement,thirdElement)
myList
## [[1]]
## [1] 1 2 3 4
## 
## [[2]]
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8   10
## 
## [[3]]
##   colOne colTwo
## 1      1    One
## 2      2    Two
## 3      4  Three
## 4      5   Four

Named lists

Just as with vectors, list elements can be assigned names.

myNamedList <- list(First=firstElement,Second=secondElement,Third=thirdElement)
myNamedList
## $First
## [1] 1 2 3 4
## 
## $Second
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8   10
## 
## $Third
##   colOne colTwo
## 1      1    One
## 2      2    Two
## 3      4  Three
## 4      5   Four

Indexing

List, as with other data types in R can be indexed. In contrast to other types, using [] on a list will subset the list to another list of selected indices. To retrieve an element from a list in R , two square brackets [[]] must be used.

myList <- list(firstElement,secondElement,thirdElement)
myList[1]
## [[1]]
## [1] 1 2 3 4
myList[[1]]
## [1] 1 2 3 4

As with data.frames, the $ sign may be used to extract named elements from a list

myNamedList$First
## [1] 1 2 3 4

Joining lists

Again, similar to vectors, lists can be joined together in R using the c() function

myNamedList <- list(First=firstElement,Second=secondElement,Third=thirdElement)
myNamedList <- c(myNamedList,list(fourth=c(4,4)))
myNamedList[c(1,4)]
## $First
## [1] 1 2 3 4
## 
## $fourth
## [1] 4 4

Joining vectors to lists

Note that on last slide we are joining two lists. If we joined a vector to a list, all elements of the vector would become list elements.

myList <- c(myList,c(4,4))
myList
## [[1]]
## [1] 1 2 3 4
## 
## [[2]]
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8   10
## 
## [[3]]
##   colOne colTwo
## 1      1    One
## 2      2    Two
## 3      4  Three
## 4      5   Four
## 
## [[4]]
## [1] 4
## 
## [[5]]
## [1] 4

Flattening lists

Sometimes you will wish to “flatten” out a list. When a list contains compatable objects, i.e. list of all one type, the unlist() function can be used. Note the maintenance of names with their additional sufficies.

myNamedList <- list(First=c(1,2,3),Second=c(2,6,7),Third=c(1,4,7))
myNamedList
## $First
## [1] 1 2 3
## 
## $Second
## [1] 2 6 7
## 
## $Third
## [1] 1 4 7
flatList <- unlist(myNamedList)
flatList[1:7]
##  First1  First2  First3 Second1 Second2 Second3  Third1 
##       1       2       3       2       6       7       1

Flattening lists to matrices

A common step is to turn a list of standard results into matrix. This can be done in a few steps in R.

myNamedList <- list(First=c(1,2,3),Second=c(2,6,7),Third=c(1,4,7))
flatList <- unlist(myNamedList)
listAsMat <- matrix(flatList,
                     nrow=length(myNamedList),
                     ncol=3,
                     byrow=T,
                     dimnames=list(names(myNamedList)))
listAsMat
##        [,1] [,2] [,3]
## First     1    2    3
## Second    2    6    7
## Third     1    4    7

Reading and writing data in R

Readding data into R

Data from External sources

Most of the time, you will not be generating data in R but will be importing data from external files.

A standard format for this data is a table

Gene_Name Sample_1.hi Sample_2.hi Sample_3.hi Sample_4.low Sample_5.low Sample_1.low
Gene_a 2.874648 4.960330 4.241958 4.998319 3.331386 3.1546449
Gene_b 2.607975 3.470672 4.788898 4.081167 3.499954 3.4684829
Gene_c 4.494620 3.335393 3.934351 2.345385 3.834476 3.0744386
Gene_d 4.465812 4.068829 5.495932 9.872878 8.675069 8.3544254
Gene_e 9.429507 11.527502 9.862680 2.910204 3.799027 0.2920961
Gene_f 9.483906 10.616366 9.591775 2.168146 3.811851 0.9630530
Gene_g 8.482135 10.623470 9.158943 10.962945 10.923468 9.8027708
Gene_h 8.632512 9.396295 10.444425 8.719504 9.368551 9.8399054

Data from text file with read.table()

Tables from text files can be read with read.table() function

Table <- read.table("data/readThisTable.csv",sep=",",header=T)
Table[1:4,1:3]
##   Gene_Name Sample_1.hi Sample_2.hi
## 1    Gene_a    4.111851    3.837018
## 2    Gene_b    6.047822    5.683518
## 3    Gene_c    2.597068    3.316300
## 4    Gene_d    6.009197    5.927419

Here we have provided two arguments. - sep argument specifies how columns are separated in our text file. (“,” for .csv, " for .tsv) - header argument specifies whether columns have headers.

Row names in read.table()

read.table() allows for significant control over reading files through its many arguments. Have a look at options by using ?read.table

The row.names argument can be used to specify a column to use as row names for the resulting data frame. Here we use the first column as row names.

Table <- read.table("data/readThisTable.csv",sep=",",header=T,row.names=1)
Table[1:4,1:3]
##        Sample_1.hi Sample_2.hi Sample_3.hi
## Gene_a    4.111851    3.837018    4.360628
## Gene_b    6.047822    5.683518    4.315889
## Gene_c    2.597068    3.316300    3.681509
## Gene_d    6.009197    5.927419    2.244701

Setting factors from read.table()

As mentioned, data which is read into R through read.table() will be of data frame class.

To avoid character columns being converted into factors, we can specify the stringsAsFactors argument here.

Table <- read.table("data/readThisTable.csv",sep=",",header=T,stringsAsFactors=F)

Other very useful functions for read table include: - skip - To set number of lines to skip when reading. - comment.char - To set the start identifier for lines not to be read.

Data from other sources

The read.table function can also read data from http.

URL <- "http://mrccsc.github.io/readThisTable.csv"
Table <- read.table(URL,sep=",",header=T)
Table[1:2,1:3]
##   Gene_Name Sample_1.hi Sample_2.hi
## 1    Gene_a    4.111851    3.837018
## 2    Gene_b    6.047822    5.683518

And the clipboard.(This is Windows version)

Table <- read.table(file="clipboard",sep=",",header=T)

Data from file columns

read.table() function will by default read every row and column of a file.

The scan() function allows for the selection of particular columns to be read into R and so can save memory when files are large.

x <- scan("data/readThisTable.csv",sep=",",
         what = c(list(""),rep(list(NULL), 6)),skip=1)
x[1:3]
## [[1]]
## [1] "Gene_a" "Gene_b" "Gene_c" "Gene_d" "Gene_e" "Gene_f" "Gene_g" "Gene_h"
## 
## [[2]]
## NULL
## 
## [[3]]
## NULL

writing data in R

Once we have our data analysed in R, we will want to export it to a file.

The most common method is to use the write.table() function

write.table(Table,file="data/readThisTable.csv",sep=",")

Since our data has column names but no row names, I will provide the arguments col.names and row.names to write.table()

write.table(Table,file="data/readThisTable.csv", sep=",", row.names =F,col.names=T)

Time for an exercise

Exercise on reading and writing data can be found here

Answers to exercise

Answers can be found here

R code for solutions can be found here

Loading Libraries

What are libraries in R?

R libraries or packages are collections of functions developed by the community. R packages include - reusable R functions - the documentation for these functions and - sample data to test their functionality.

What are repositories?

A repository is a place where packages are deposited by the community and you can install them from it. The two most popular repositories for R packages are: - CRAN - Bioconductor

How to install R packages from CRAN?

You can install the packages from CRAN using the function install.packages()

For example,

install.packages("babynames")

To load the installed packages and use them, you can use the library() function

For example,

library(babynames)

You can also install packages through the R studio menu

-> Tools -> Install packages ..

How to install R packages from Bioconductor?

To install packages from Bioconductor, you have to first have to install the Bioconduction package manager “BiocManager”

To install it,

install.packages("BiocManager")

Then, you can install any packages from Bioconductor using the BiocManager::install() function

For example,

BiocManager::install("DESeq2")

To load the installed packages and use them, you can use the library() function

For example,

library(DESeq2)

How to install R packages from Bioconductor in older versions of R?

If you are using an older version of R (R < 3.5.0), you have to use biocLite to install Bioconductor packages.

To install packages from Bioconductor, you have to first source the “biocLite” package.

source("https://bioconductor.org/biocLite.R")

Then, you can install any packages from Bioconductor using the biocLite() function

For example,

biocLite("DESeq2")

To load the installed packages and use them, you can use the library() function

For example,

library(DESeq2)

How to get help about the packages?

You can get the documentation of the package by using the function help() or “??”

For example

help(babynames)

# Or you can use "??"
?? babynames

For a more detailed information on each and every parameter of all the functions in a package, you can refer to the reference manual or the in the package webpage or by using the browseVignettes() function.

For example,

browseVignettes("DESeq2")

You can see what libraries are available in the Packages panel or by the library() function with no arguments supplied

library()

End of Session 1