Statistical Methods with R

Writing R Code

Unit A · Chapter 02 · Lecture 02b

Developed by Jeffrey M. Girard

Roadmap: Basic Programming

  1. Assignment

  2. Naming

  3. Functions

  4. Vectors

Assignment

Assignment

  • It helps to store data in named objects
    • This makes data easier to use and re-use
    • And the code easier to write and read
  • Which command is easier to follow?
    1. Dial 7 8 5 8 6 4 0 8 4 1
    2. Call Office Phone
  • Named objects come from assignment
    • Give a name then an arrow then the data

Form

name <- value

Example

office <- 7858640841

Assigning and Printing

# Store the value 2 under the name x
x <- 2

# Typing the name on its own prints the value
x
[1] 2

<- stores a value under a name. Assigning prints nothing; typing the name on its own is how you ask R to show you what it holds.

Using an Object in Math

# Once x exists, it stands in for its value
x * 4
[1] 8
# It can appear as many times as you like in one line
(10 + x - 1) / x
[1] 5.5

Wherever a value could go, a name holding that value can go instead, as often as you need it.

Updating Requires Assignment

# Using x does not change it
x + 1
[1] 3
# x is still 2
x
[1] 2
# To update it, assign the result back to the name
x <- x + 1
x
[1] 3

Using an object never changes it. To update one, assign the result back to the same name.

Objects Can Create Other Objects

# The right-hand side can use objects that already exist
y <- 10 + x
y
[1] 13
# And a line can use several objects at once
y / x
[1] 4.333333

The right-hand side of <- is just an expression, so it can use any objects that already exist. That is how a script builds up from one line to the next.

Naming

Naming

  • Object names can only include:
    • Letters: a-Z
    • Numbers: 0-9
    • Underscores: _
    • Periods: .
  • Additional Rules:
    • Must start with a letter (or a period)
    • Cannot contain spaces or dashes
    • Cannot contain other symbols
    • Names are case-sensitive (age ≠ Age)

Good Names are a Balancing Act

x <- 93 # legal, but what is it?

rate <- 93 # too short to be clear

heart_rate_in_beats_per_minute <- 93 # too long to type

heart_rate_bpm <- 93 # just right

A good name is the shortest one a reader can still understand six months later.

Pitfall: No Spaces or Dashes

heart rate <- 93
Error: unexpected symbol in "heart rate"
heart-rate <- 93
Error:
! object 'heart' not found

A space stops R mid-line. A dash is worse: R reads heart-rate as heart minus rate, so it fails looking for an object rather than telling you the name is illegal. Use an underscore: heart_rate.

Pitfall: No Special Symbols

age@time2 <- 12
Error:
! object 'age' not found
age_time2 <- 12 # correct
age_time2
[1] 12

@ already means something else in R, so it reads age@time2 as an operation on an object called age. Letters, numbers, _ and . are all a name may hold.

Pitfall: Names Must Start with a Letter

1_heart_rate <- 93
Error: unexpected input in "1_"
_heart_rate <- 93
Error: unexpected symbol in "_heart_rate"
heart_rate_1 <- 93 # correct: the digit comes last
heart_rate_1
[1] 93

Move the digit to the end and the name is fine.

Names are Case-Sensitive

heart_rate <- 93
Heart_rate <- 88

# These are two entirely different objects
heart_rate
[1] 93
Heart_rate
[1] 88

One capital letter makes an entirely different object. R will not warn you, because it has no way to know you meant the other one.

Functions

Functions

  • Recipes allow chefs to cook up tasty treats
    • Recipes call for ingredients
    • Recipes involve one or more steps
    • Steps transform ingredients into treats
  • Functions are like customizable recipes
    • Functions call for inputs (“arguments”)
    • Functions involve one or more lines
    • Code transforms inputs into outputs
    • Functions usually need parentheses

Form

output <- fn(input)

Example

out <- f(in1, in2)

Functions Do a Task More Readably

output <- function_name(input)

# The hard way
9 ^ (1 / 2)
[1] 3
# The readable way
x <- sqrt(9)
x
[1] 3

A function gives a name to something you would otherwise have to spell out. It is easier to write, and far easier to read back.

What Can Go Inside a Function

y <- 9

# The input can be an object rather than a literal value
sqrt(y)
[1] 3
# Or the result of a calculation
round(2 / 3)
[1] 1

Anything that produces a value can go in the input slot: a literal, an object, or another calculation. R works out the inside first, then hands the result over.

Arguments Customize a Function

output <- function_name(argument, argument_name = argument_value)

round(2 / 3, digits = 2)
[1] 0.67
# digits has a default of 0, so this...
round(2 / 3)
[1] 1
# ...means exactly the same thing as this
round(2 / 3, digits = 0)
[1] 1

Extra arguments change how a function does its job. Most have a default, which is what you get when you leave them out.

Vectors

Vectors

  • Vectors combine similar objects into a collection
    • I like to imagine a train pulling multiple cars
    • A vector is one object with many sub-objects
    • We refer to each sub-object as an element
  • Some functions transform each element in turn
    • Double the amount of cargo in every train car
  • Some functions summarize across elements
    • Calculate the total cargo across all train cars

Form

name <- c(value, value)

Example

v <- c(1, 2, 3)

Combining Elements into a Vector

vector_name <- c(element1, element2, element3)

x <- 4 9 16 25
Error: unexpected numeric constant in "x <- 4 9"
x <- c(4, 9, 16, 25)
x
[1]  4  9 16 25
y <- c(2, 3)
y
[1] 2 3

Elements must be separated by commas and wrapped in c(). Without it R sees several values where it expected one.

Combining Vectors and Elements

# c() also joins whole vectors together
c(x, y)
[1]  4  9 16 25  2  3
# And vectors and single elements
c(x, y, 20)
[1]  4  9 16 25  2  3 20

c() flattens whatever you give it into one vector, so there is no such thing as a vector nested inside another.

Math Transforms Each Element

x + 1
[1]  5 10 17 26
x * 3
[1] 12 27 48 75
# But as before, nothing is saved without assignment
x
[1]  4  9 16 25

An operation applies to every element at once, with no loop to write. As with a single value, the result is not saved unless you assign it.

Functions That Transform

sqrt(x)
[1] 2 3 4 5
log(x)
[1] 1.386294 2.197225 2.772589 3.218876

These return a vector as long as the input: one answer per element.

Functions That Summarize

length(x)
[1] 4
sum(x)
[1] 54
mean(x)
[1] 13.5
average(x)
Error in `average()`:
! could not find function "average"

These collapse the whole vector to a single number. Note the last one: R names this function mean(), and a reasonable guess is still an error.

Pitfall: Missing Values are Contagious

scores <- c(10, 12, 20, NA, 8)

# NA spreads: the mean depends on the value we do not have
mean(scores)
[1] NA
# Ask for the mean of the non-missing values instead
mean(scores, na.rm = TRUE)
[1] 12.5

NA means “we do not know”, so any answer depending on it is also unknown. That is a feature, not a bug. na.rm = TRUE answers from what you have.