Intro to R Markdown

print("Hello World!")
## [1] "Hello World!"

Outline

Topics covered in this module:

  1. Free memory in R
  2. Basic math
  3. Variables
  4. Four main data types, i.e. numeric, character(string), Date/POSIXct(time-based), and logical
  5. Four main data structure, i.e. vector, list, matrix and data.frame
  6. Function documentation
  7. Missing data
  8. Pipes

R is a powerful tool for all manner of calculations, data manipulation and scientific computations. Before getting to the complex operations possible in R we must start with the basics. Like most languages R has its share of mathematical capability, variables, functions and data types.

1. Free Memory in R

# clear environment
rm(list = ls())
# clear r console
cat("\014")

2. Basic Math

At a basic level, we can use R as a calculator to compute simple sums with the +, -, * (for multiplication) and / (for division) symbols.

3 / 3
## [1] 1
3 + 3
## [1] 6
3 * 3
## [1] 9
3^2
## [1] 9
T
## [1] TRUE
3 * (2 + 4)
## [1] 18
(4 * 6) + 5
## [1] 29
4 * (6 + 5)
## [1] 44

R is capable of more complicated arithmetic such as trigonometry and logarithms.

pi
## [1] 3.141593
sin(pi/2)
## [1] 1
cos(pi)
## [1] -1
tan(1)
## [1] 1.557408
log(1)
## [1] 0
## 3. Variables


x <- 2
myNumber <- 36
y<-3
y < -3
## [1] FALSE

We can perform arithmetic on variables using functions:

sqrt(myNumber)
## [1] 6

We can add variables together:

x + myNumber
## [1] 38

We can update the value of an existing variable:

(x <- 21)
## [1] 21

We can set one variable to equal the value of another variable:

(x <- myNumber)
## [1] 36

We can update the value of a variable:

(myNumber <- myNumber + sqrt(16))
## [1] 40

4. Four Main Data Types

There are numerous data types in R that store various kinds of data. The four main types of data most likely to be used are:

The type of data contained in a variable is checked with the class() function:

is.numeric(x)
## [1] TRUE

4.1 Numeric Data

Numeric data is the most common type in R. The most commonly used numeric data is numeric. This is similar to a float or double in other languages. It handles integers and decimals, both positive and negative, and of course, zero. A numeric value stored in a variable is automatically assumed to be numeric. Testing whether a variable is numeric is done with the function is.numeric():

4.2 Character Data

The character (string) data type is very common in statistical analysis and must be handled with care. R has two primary ways of handling character data: character and factor. While they may seem similar on the surface, they are treated quite differently.

(x <- "data")
## [1] "data"
(y <- factor("data"))
## [1] data
## Levels: data
  • Notice that x contains the word "data" in quotes, while y has the word data without quotes and a second line of information about the levels of y. We will explain this in Vectors.

  • Characters are case sensitive, so Data is different from data or DATA.

  • To find the length of a character use the nchar() function.

nchar(x)
## [1] 4
nchar("hello world!!")
## [1] 13

4.3 Dates

Dealing with dates and times can be difficult in any language, and to further complicate matters R has numerous different types of dates.

  • The most useful are Date and POSIXct.

  • Date stores just a date while POSIXct stores a date and time.

  • Both objects are actually represented as the number of days (Date) or seconds (POSIXct) since January 1, 1970.

(date1 <- as.Date("2012-06-28"))
## [1] "2012-06-28"
class(date1)
## [1] "Date"
as.numeric(date1)
## [1] 15519
(date2 <- as.POSIXct("2012-06-28 17:42"))
## [1] "2012-06-28 17:42:00 EDT"
class(date2)
## [1] "POSIXct" "POSIXt"
as.numeric(date2)
## [1] 1340919720

4.4 Logical

Logicals are a way of representing data that can be either TRUE or FALSE. Numerically, TRUE is the same as 1 and FALSE is the same as 0. So TRUE * 5 equals 5 while FALSE * 5 equals 0.

TRUE * 5
## [1] 5
FALSE * 5
## [1] 0

R provides T and F as shortcuts for TRUE and FALSE, respectively, but it is best practice not to use them, as they are simply variables storing the values TRUE and FALSE and can be overwritten, which can cause a great deal of frustration as seen in the following example.

T
## [1] TRUE
class(T)
## [1] "logical"
T <- 7
class(T)
## [1] "numeric"

Logicals can result from comparing two numbers, or characters.

2 == 3
## [1] FALSE
2 != 3
## [1] TRUE
2 <= 3
## [1] TRUE
2 > 3
## [1] FALSE
2 >= 3
## [1] FALSE
"data" == "stats"
## [1] FALSE

5. Four Main Data Structure

There are four data structures that you will use the most in R: vectors, lists, matrices, and data frames.

5.1 Vectors

  • A vector is a collection of ordered homogeneous elements, i.e. all of the same type. For instance, c(1, 3, 2, 1, 5) is a vector consisting of the numbers 1, 3, 2, 1, 5, in that order.

  • Similarly, c("R", "Excel", "SAS", "Excel") is a vector of the character elements, “R”, “Excel”, “SAS”, and “Excel”. A vector cannot be of mixed type.

  • Vectors play a crucial, and helpful, role in R. More than being simple containers, vectors in R are special in that R is a vectorized language, meaning operations are applied to each element of the vector automatically, without the need to loop through the vector.

  • Vectors do not have a dimension, meaning there is no such thing as a column vector or row vector. These vectors are not like the mathematical vector, where there is a difference between row and column orientation.

  • The most common way to create a vector is with c(). The c stands for combine because multiple elements are being combined into a vector.

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

For vector operations, no loops are necessary.

x * 3
##  [1]  3  6  9 12 15 18 21 24 27 30
x + 3
##  [1]  4  5  6  7  8  9 10 11 12 13
x + 2
##  [1]  3  4  5  6  7  8  9 10 11 12
x - 2
##  [1] -1  0  1  2  3  4  5  6  7  8
x / 4
##  [1] 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00 2.25 2.50
x^2
##  [1]   1   4   9  16  25  36  49  64  81 100
sqrt(x)
##  [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427
##  [9] 3.000000 3.162278

A shortcut to create a vector is the : operator, which generates a sequence of consecutive numbers, in either direction.

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

Vector operations can be extended even further. Let’s say we have two vectors of equal length. Each of the corresponding elements can be operated on together. When operating on two vectors of unequal length, the shorter vector gets recycled—that is, its elements are repeated, in order, until they have been matched up with every element of the longer vector.

x <- 1:10
y <- -5:4
x + y
##  [1] -4 -2  0  2  4  6  8 10 12 14
x - y
##  [1] 6 6 6 6 6 6 6 6 6 6
x * y
##  [1] -5 -8 -9 -8 -5  0  7 16 27 40
x/y
##  [1] -0.2 -0.5 -1.0 -2.0 -5.0  Inf  7.0  4.0  3.0  2.5
x^y
##  [1] 1.000000e+00 6.250000e-02 3.703704e-02 6.250000e-02 2.000000e-01
##  [6] 1.000000e+00 7.000000e+00 6.400000e+01 7.290000e+02 1.000000e+04
length(x)
## [1] 10
x + c(1,2)
##  [1]  2  4  4  6  6  8  8 10 10 12
x <= 5
##  [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE

We can also create a vector of characters.

q <- c("Hockey", "Football", "Baseball", "Curling", "Rugby", "Lacrosse", "Basketball", "Tennis", "Cricket", "Soccer")

Accessing individual elements of a vector is done using square brackets ([ ]). The first element of x is retrieved by typing x[1], the first two elements by x[1:2] and nonconsecutive elements by x[c(1, 4)].

x[1]
## [1] 1
x[1:2]
## [1] 1 2
x[c(1, 4)]
## [1] 1 4

This works for all types of vectors whether they are numeric, logical, character and so forth.

Factors are an important concept in R, especially when building models. Let’s create a simple vector of text data that has a few repeats. We will start with the vector q we created earlier and add some elements to it.

q2 <- c(q, "Hockey", "Lacrosse", "Hockey", "Water Polo", "Hockey", "Lacrosse")

Converting this to a factor is easy with as.factor().

(q2Factor <- as.factor(q2))
##  [1] Hockey     Football   Baseball   Curling    Rugby      Lacrosse  
##  [7] Basketball Tennis     Cricket    Soccer     Hockey     Lacrosse  
## [13] Hockey     Water Polo Hockey     Lacrosse  
## 11 Levels: Baseball Basketball Cricket Curling Football Hockey ... Water Polo
  • Notice that after printing out every element of q2Factor, R also prints the levels of q2Factor.
  • The levels of a factor are the unique values of that factor variable.
  • Technically, R is giving each unique value of a factor a unique integer, tying it back to the character representation. This can be seen with as.numeric().
as.numeric(q2Factor)
##  [1]  6  5  1  4  8  7  2 10  3  9  6  7  6 11  6  7

5.2 Lists

Often a container is needed to hold arbitrary objects of either the same type or varying types. R accomplishes this through lists. They store any number of items of any type. A list can contain all numerics or characters or a mix of the two or data.frames or, recursively, other lists.

Lists are created with the list() function where each argument to the function becomes an element of the list.

list <- list(1, 2, 3)
list2 <- list(c(1, 2, 3))
(list3 <- list(c(1, 2, 3), 3:7))
## [[1]]
## [1] 1 2 3
## 
## [[2]]
## [1] 3 4 5 6 7

Lists can have names. Each element has a unique name that can be either viewed or assigned using names().

(list4 <- list(list3, 1:10))
## [[1]]
## [[1]][[1]]
## [1] 1 2 3
## 
## [[1]][[2]]
## [1] 3 4 5 6 7
## 
## 
## [[2]]
##  [1]  1  2  3  4  5  6  7  8  9 10

Names can also be assigned to list elements during creation using name-value pairs.

names(list4)
## NULL
(names(list4) <- c("list", "vector"))
## [1] "list"   "vector"
list4
## $list
## $list[[1]]
## [1] 1 2 3
## 
## $list[[2]]
## [1] 3 4 5 6 7
## 
## 
## $vector
##  [1]  1  2  3  4  5  6  7  8  9 10
(list5 <- list(Name = "Kevin", Age = 25, Education = "MS"))
## $Name
## [1] "Kevin"
## 
## $Age
## [1] 25
## 
## $Education
## [1] "MS"
names(list5)
## [1] "Name"      "Age"       "Education"
length(list5)
## [1] 3
list5$Name
## [1] "Kevin"
list5[1]
## $Name
## [1] "Kevin"

Note that the named values in the list can be accessed using the dollar operator ($). Once referenced, they can be read or written. This is also how new items can be added to the list.

list5$Gender <- "Male"
list5
## $Name
## [1] "Kevin"
## 
## $Age
## [1] 25
## 
## $Education
## [1] "MS"
## 
## $Gender
## [1] "Male"

5.3 Matrices

A matrix is a table of data. It has dimensions, i.e. rows and columns. Also, matrices can have row and column names, which can be determined and/or assigned by rownames() and colnames(). Other functions work for matrices include nrow(), ncol(), dimnames().

Let’s create a 2-row, 3-column, i.e. 2 by 3, matrix with named headings

dat <- c(1, 2, 3, 4, 5, 6)
headings <- list(c(1,2), c("A","B","C"))
mat1 <- matrix(data = dat , nrow = 2, ncol = 3, byrow = TRUE, dimnames = headings)
mat1[,] # all data
##   A B C
## 1 1 2 3
## 2 4 5 6
mat1[1,]
## A B C 
## 1 2 3
mat1[,1]
## 1 2 
## 1 4

A lot of useful plotting and machine learning algorithms require the data to be provide as a matrix.

5.4 Data Frames

Data frames are useful for actually representing tables of your data in R. A list with possible heterogeneous vector elements of the same length. The elements of a data frame can be numeric vectors, factor vectors, and logical vectors, but they must all be of the same length.

Let’s create a data frame:

(year <- c(2020, 2021, 2022, 2020, 2021, 2022, 2020, 2021, 2022))
## [1] 2020 2021 2022 2020 2021 2022 2020 2021 2022
(score <- c(34, 44, 83, 34, 44, 83, 34, 44, 83))
## [1] 34 44 83 34 44 83 34 44 83
df <- data.frame(year, score)
df
##   year score
## 1 2020    34
## 2 2021    44
## 3 2022    83
## 4 2020    34
## 5 2021    44
## 6 2022    83
## 7 2020    34
## 8 2021    44
## 9 2022    83
head(df) # print out the first 6 rows of the data frame
##   year score
## 1 2020    34
## 2 2021    44
## 3 2022    83
## 4 2020    34
## 5 2021    44
## 6 2022    83
plot(df$score)

df[,1]
## [1] 2020 2021 2022 2020 2021 2022 2020 2021 2022
df[1,]
##   year score
## 1 2020    34
df$score
## [1] 34 44 83 34 44 83 34 44 83
  • A matrix is much simpler structure, intended for mathematical operations.
  • A data frame is more suited to representing a table of data and is expected by modern implementations of machine learning algorithms in R.
  • Note that you can index into rows and columns of a data frame just like you can for a matrix.
  • Also note that you can reference a column using its name, e.g. df$score.

6. Function Documentation

Any function provided in R has accompanying documentation. The easiest way to access that documentation is to place a question mark in front of the function name, like this: ?mean. To get help on operators like +, * or == surround them with back ticks (```):

?`+`
?`*`
?`==`

There are occasions when we have only a sense of the function we want to use. In that case we can look up the function by using part of the name with apropos().

apropos("mea")
##  [1] ".colMeans"          ".rowMeans"          "colMeans"          
##  [4] "influence.measures" "kmeans"             "mean"              
##  [7] "mean.Date"          "mean.default"       "mean.difftime"     
## [10] "mean.POSIXct"       "mean.POSIXlt"       "rowMeans"          
## [13] "weighted.mean"

7. Missing Data

Missing data plays a critical role in both statistics and computing, and R has two types of missing data, NA and NULL. While they are similar, they behave differently and that difference needs attention.

7.1 NA

Statistical programs use various techniques to represent missing data such as a dash, a period or even the number 99. R uses NA. NA will often be seen as just another element of a vector. is.na() tests each element of a vector for missingness.

z <- c(1, 2, NA, 8, 3, NA, 3)
z
## [1]  1  2 NA  8  3 NA  3
is.na(z)
## [1] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE

If we calculate the mean of z, the answer will be NA since mean returns NA if even a single element is NA.

mean(z)
## [1] NA

When the na.rm is TRUE, mean first removes the missing data, then calculates the mean.

mean(z, na.rm=TRUE)
## [1] 3.4

There is similar functionality with sum(), min(), max(), var(), sd() and other functions

7.2 NULL

NULL is the absence of anything. It is not exactly missingness, it is nothingness. Functions can sometimes return NULL and their arguments can be NULL. An important difference between NA and NULL is that NULL cannot exist within a vector. If used inside a vector, it simply disappears.

z <- c(1, NULL, 3)
z
## [1] 1 3

8. Pipes

A new paradigm for calling functions in R is the pipe. The pipe from the magrittr package works by taking the value or object on the left-hand side of the pipe and inserting it into the first argument of the function that is on the right-hand side of the pipe. A simple example example would be using a pipe to feed x to the mean function.

library(magrittr)
x <- 1:10
mean(x)
## [1] 5.5

The result is the same but they are written differently. Pipes are most useful when used in a pipeline to chain together a series of function calls.

For example, given a vector z that contains numbers and NAs, we want to find out how many NAs are present. Traditionally, this would be done by nesting functions.

z <- c(1, 2, NA, 8, 3, NA, 3)
sum(is.na(z))
## [1] 2

This can also be done using pipes.

Pipes are used extensively in a number of modern packages after being popularized by Hadley Wickham in the dplyr package.