# 1 Working with vectors

## 1.1 Intro

Vectors are the building blocks of R. They are 1D arrays that contain data of all the same type - so coercion of data types happens.

• R is a 1-based array system so a vector starts at position 1
• Items in a vector can have names but can also be referred to by position

## 1.2 Create

You can create vectors using the c() function or via a sequence (:). Values in a vector can be given names - this can be useful when subsetting values.

handCrafted<-c(1,2,3,4)
seqCrafted<-1:4
named<-c(a=1,b=2,c=3,d=4)
named
## a b c d
## 1 2 3 4

## 1.3 Filter

Alternatively called subsetting, we can filter a vector by using positive notations of position, negative notations of position, the name of a value, or providing a boolean value for each item in the vector.

handCrafted[1]
## [1] 1
seqCrafted[-1]
## [1] 2 3 4
named["b"]
## b
## 2
handCrafted[c(rep(TRUE,3),FALSE)]
## [1] 1 2 3

## 1.4 Update

You can update one or more values in a vector by assigning the new values into the desired subset.

handCrafted
## [1] 1 2 3 4
handCrafted[2]<-99
handCrafted
## [1]  1 99  3  4
named
## a b c d
## 1 2 3 4
named["a"]<-99
named
##  a  b  c  d
## 99  2  3  4
# Delete by subsetting without value
seqCrafted
## [1] 1 2 3 4
seqCrafted<-seqCrafted[-4]
seqCrafted
## [1] 1 2 3
# Append by creating a vector combining the original and the additional values
ordered
## function (x, ...)
## factor(x, ..., ordered = TRUE)
## <bytecode: 0x38b7130>
## <environment: namespace:base>
ordered<-c(ordered,5)
ordered
## [[1]]
## function (x, ...)
## factor(x, ..., ordered = TRUE)
## <bytecode: 0x38b7130>
## <environment: namespace:base>
##
## [[2]]
## [1] 5

## 1.5 Manipulate

You can manipulate a vector using functions. You can overwrite any object created - this will change mode, class, etc as R is loosely typed and doesn’t require such things to be specified and fixed up front.

mode(seqCrafted)
## [1] "numeric"
seqCrafted<-as.character(seqCrafted)
mode(seqCrafted)
## [1] "character"

## 1.6 Order

Ordering of records works by providing the position numbers of values in a vector and then using those to produce a vector with the original components in new locations

preOrder<-sample(letters, 6)
preOrder
## [1] "n" "a" "x" "z" "s" "q"
# Get order the values should appear in to be alphabetised
order(preOrder)
## [1] 2 1 6 5 3 4
# Use it to sort a vector
ordered<-preOrder[order(preOrder)]
ordered
## [1] "a" "n" "q" "s" "x" "z"
# Alternatively, use the sort() function for brevity
sorted<-sort(preOrder)
sorted
## [1] "a" "n" "q" "s" "x" "z"

You can extract various pieces of information about a vector

names(handCrafted)
## NULL
names(named)
## [1] "a" "b" "c" "d"
dim(named)
## NULL
dimnames(named)
## NULL
length(named)
## [1] 4
class(named)
## [1] "numeric"
mode(named)
## [1] "numeric"
attributes(named)
## $names ## [1] "a" "b" "c" "d" str(named) ## Named num [1:4] 99 2 3 4 ## - attr(*, "names")= chr [1:4] "a" "b" "c" "d" ## 1.8 Exercises 1. Create a vector containing upper case and lower case variants of the alphabet 2. Create a new vector with a random sample of your new letter vector 3. Filter out any lowercase letters ## 1.9 Answers #1 lets<-c(LETTERS,letters) #2 lets<-sample(lets,50) #3 lets<-lets[tolower(lets)!=lets] lets ## [1] "M" "R" "B" "J" "D" "Z" "K" "F" "N" "Y" "Q" "H" "E" "U" "C" "V" "T" ## [18] "O" "X" "S" "L" "I" "G" "P" "A" # 2 Working with lists ## 2.1 Intro Lists hold multiple objects together and form the basis of complex data objects like data.frames and model results. ## 2.2 Create You can create lists using the list() function or via a sequence (:). Objects in a list can be given names. basicList<-list(c(1,2,3,4),LETTERS[5:8], rnorm(5)) namedList<-list(p1=c(1,2,3,4),p2=LETTERS[5:8]) ## 2.3 Filter Alternatively called subsetting, we can filter a list by using positive notations of position, negative notations of position, or the name of a element, or providing a boolean value for each item in the list. We can also use list[[ "elementname" ]] or list$elementname for specifically detailing a single element.

basicList[1]
## [[1]]
## [1] 1 2 3 4
basicList[-1]
## [[1]]
## [1] "E" "F" "G" "H"
##
## [[2]]
## [1] -0.05155527  0.62289312 -0.31181880 -0.90420387 -1.40879209
namedList["p2"]
## $p2 ## [1] "E" "F" "G" "H" basicList[c(TRUE,FALSE)] ## [[1]] ## [1] 1 2 3 4 ## ## [[2]] ## [1] -0.05155527 0.62289312 -0.31181880 -0.90420387 -1.40879209 basicList[[1]] ## [1] 1 2 3 4 basicList[[-1]] ## Error in basicList[[-1]]: attempt to select more than one element in get1index <real> namedList[["p2"]] ## [1] "E" "F" "G" "H" namedList$p2
## [1] "E" "F" "G" "H"
basicList[[c(TRUE,TRUE)]]
## [1] 1

## 2.4 Update

You can update one or more objects in a list by assigning the new values into the desired object using the same subsetting capabilities as noted in the Filter section.

basicList[[1]]<-8:12
basicList[1]
## [[1]]
## [1]  8  9 10 11 12
# Elements in a list can be removed by making them NULL
basicList[2]
## [[1]]
## [1] "E" "F" "G" "H"
basicList[2]<-NULL
basicList[2]
## [[1]]
## [1] -0.05155527  0.62289312 -0.31181880 -0.90420387 -1.40879209
# Append by creating a list combining the original and the additional values
basicList[[3]]<-LETTERS[5:8]

## 2.5 Manipulate

You can manipulate a list using functions, and also manipulate the objects stored in the list.

lapply(basicList,mode)
## [[1]]
## [1] "numeric"
##
## [[2]]
## [1] "numeric"
##
## [[3]]
## [1] "character"

## 2.6 Order

Ordering of objects in a list is rarely required but you can do it with the order() function.

unorderedList<-list(p2=c(1,2,3,4),p1=LETTERS[5:8])
unorderedList[order(names(unorderedList))]
## $p1 ## [1] "E" "F" "G" "H" ## ##$p2
## [1] 1 2 3 4

You can extract various pieces of information about a list

names(basicList)
## NULL
names(namedList)
## [1] "p1" "p2"
dim(namedList)
## NULL
dimnames(namedList)
## NULL
length(namedList)
## [1] 2
class(namedList)
## [1] "list"
mode(namedList)
## [1] "list"
attributes(namedList)
## $names ## [1] "p1" "p2" str(namedList) ## List of 2 ##$ p1: num [1:4] 1 2 3 4
##  $p2: chr [1:4] "E" "F" "G" "H" ## 2.8 Exercise Create a linear regression model (lm()) for the iris dataset and extract the fitted.values element ## 2.9 Answers irisLM<-lm(Sepal.Width~Sepal.Length, iris) head(irisLM$fitted.values)
##        1        2        3        4        5        6
## 3.103334 3.115711 3.128088 3.134277 3.109523 3.084769

# 3 Working with tables

## 3.1 Intro

Tables or data.frame’s as the base structure is called in R can hold multiple columns of different data types. Normally, data.table or dplyr would be taught to super-charge data.frames (see Steph’s extended session “Cut the R learning curve” for more on these) but to reduce dependencies and make it easier to transfer code between different systems, we’ll use just base R.

• data.frames have a coordinate system like excel so df[ 1 , 2 ] selects the intersection of row 1 and column 2
• Rows and columns can be referenced by name
• A data.frame is actuallly a list that is presented like a table

## 3.2 Create

You can create data.frames using the data.frame() function.

• data.frame() will error if you try storing something odd in it. Use as.data.frame() to coerce
df<-data.frame(a=1:4, b=LETTERS[5:8], c=rnorm(4),row.names = letters[9:12])
df
##   a b          c
## i 1 E  0.2731886
## j 2 F -0.8659110
## k 3 G  1.0832867
## l 4 H  0.7483340

## 3.3 Filter

Alternatively called subsetting, we can filter a data.frame by using positive notations of position, negative notations of position, or the name of a element, or providing a boolean value for each item in the list.

To filter using a condition requires the creation of a boolean vector based on a specific column. columns can be treated as vectors by using df$colname df[1, ] ## a b c ## i 1 E 0.2731886 df[ ,1] ## [1] 1 2 3 4 df[1,1] ## [1] 1 df[-(3:4),] ## a b c ## i 1 E 0.2731886 ## j 2 F -0.8659110 df[,"a"] ## [1] 1 2 3 4 df[ , c(TRUE, TRUE, FALSE)] ## a b ## i 1 E ## j 2 F ## k 3 G ## l 4 H df[df$a<4,]
##   a b          c
## i 1 E  0.2731886
## j 2 F -0.8659110
## k 3 G  1.0832867

## 3.4 Update

You can update values in a data.frame by referencing it’s position using the same subsetting capabilities as noted in the Filter section.

df[1,1]<-2
df
##   a b          c
## i 2 E  0.2731886
## j 2 F -0.8659110
## k 3 G  1.0832867
## l 4 H  0.7483340
# Columns in a data.frame can be removed by making them NULL
df[,2]
## [1] E F G H
## Levels: E F G H
df[,2]<-NULL
df[,2]
## [1]  0.2731886 -0.8659110  1.0832867  0.7483340
# Rows in a data.frame can be removed by subsetting without them
df[2,]
##   a         c
## j 2 -0.865911
df<-df[-2,]
df[2,]
##   a        c
## k 3 1.083287
# Appends can happen in a variety of ways
superDF<-data.frame(df,d=5:7)
superDF
##   a         c d
## i 2 0.2731886 5
## k 3 1.0832867 6
## l 4 0.7483340 7
df$newcol<-5:7 df ## a c newcol ## i 2 0.2731886 5 ## k 3 1.0832867 6 ## l 4 0.7483340 7 df[4,]<-c(1,1,1) df ## a c newcol ## i 2 0.2731886 5 ## k 3 1.0832867 6 ## l 4 0.7483340 7 ## 4 1 1.0000000 1 ## 3.5 Order Ordering of data.frames works by providing the position numbers of row numbers in a vector and then using these to return data.frame rows in a specific order # Get order the values should appear in order(df$c)
## [1] 1 3 4 2
# Use it to sort a table
ordered<-df[order(df$c),] ordered ## a c newcol ## i 2 0.2731886 5 ## l 4 0.7483340 7 ## 4 1 1.0000000 1 ## k 3 1.0832867 6 ## 3.6 Metadata You can extract various pieces of information about a list names(df) ## [1] "a" "c" "newcol" dim(df) ## [1] 4 3 dimnames(df) ## [[1]] ## [1] "i" "k" "l" "4" ## ## [[2]] ## [1] "a" "c" "newcol" length(df) ## [1] 3 class(df) ## [1] "data.frame" mode(df) ## [1] "list" attributes(df) ##$names
## [1] "a"      "c"      "newcol"
##
## $row.names ## [1] "i" "k" "l" "4" ## ##$class
## [1] "data.frame"
str(df)
## 'data.frame':    4 obs. of  3 variables:
##  $a : num 2 3 4 1 ##$ c     : num  0.273 1.083 0.748 1
##  $newcol: num 5 6 7 1 ## 3.7 Exercises 1. Make a copy of the iris dataset to play with 2. Add a column with the estimated area of the sepals 3. Filter out any record with a petal width lower than average 4. Sort by species name in descending order ## 3.8 Answers #1 myIris<-iris #2 myIris$Sepal.Area<-myIris$Sepal.Width * myIris$Sepal.Length
#3
avg<-mean(myIris$Petal.Width) myIris<-myIris[myIris$Petal.Width>=avg,]
#4
myIris<-myIris[order(myIris\$Species,decreasing = TRUE),]
head(myIris)
##     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species Sepal.Area
## 101          6.3         3.3          6.0         2.5 virginica      20.79
## 102          5.8         2.7          5.1         1.9 virginica      15.66
## 103          7.1         3.0          5.9         2.1 virginica      21.30
## 104          6.3         2.9          5.6         1.8 virginica      18.27
## 105          6.5         3.0          5.8         2.2 virginica      19.50
## 106          7.6         3.0          6.6         2.1 virginica      22.80`