Chapter 1 R Foundations

R is a programming language designed for statistical computing and data analysis. Its most important practical idea is vectorization: many operations work on an entire vector rather than requiring an explicit loop.

1.1 Objects and assignment

Use <- for assignment in book and analysis code. Names should describe the meaning of an object rather than its storage type.

sample_size <- 100L
conversion_rate <- 0.18
campaign_name <- "Summer launch"
is_complete <- FALSE

sample_size
#> [1] 100

The L suffix creates an integer. A number such as 0.18 is stored as a double. Use typeof() for the underlying storage type and class() for the object-oriented class used by generic functions.

typeof(sample_size)
#> [1] "integer"
typeof(conversion_rate)
#> [1] "double"
class(campaign_name)
#> [1] "character"
class(is_complete)
#> [1] "logical"

1.2 Atomic vectors

An atomic vector contains values of one underlying type. Arithmetic and most base R functions operate element by element.

revenue <- c(120, 150, 135, 180)
revenue * 1.05
#> [1] 126.00 157.50 141.75 189.00
mean(revenue)
#> [1] 146.25

When values of different types are combined, R coerces them to a common type. This can be useful, but accidental coercion is a common source of bugs.

mixed <- c(10, TRUE, "20")
mixed
#> [1] "10"   "TRUE" "20"
typeof(mixed)
#> [1] "character"

Here every value becomes character because character is the most flexible of the supplied types. Convert deliberately with functions such as as.integer(), as.double(), and as.character().

1.3 Missing values

NA represents a missing value. Most summary functions propagate missingness unless the analyst explicitly chooses to remove missing values.

scores <- c(82, 91, NA, 88)

mean(scores)
#> [1] NA
mean(scores, na.rm = TRUE)
#> [1] 87
is.na(scores)
#> [1] FALSE FALSE  TRUE FALSE

Do not test missingness with x == NA; the result is unknown rather than TRUE or FALSE. Use is.na(x).

1.4 Comparisons and logical operators

Use & and | for element-wise comparisons. Use && and || only when a single Boolean decision is intended, such as the condition in an if statement.

values <- 1:6
values > 2 & values < 6
#> [1] FALSE FALSE  TRUE  TRUE  TRUE FALSE
values[values > 2 & values < 6]
#> [1] 3 4 5

%in% is useful for membership checks and never returns NA for ordinary missing-value comparisons.

requested_ids <- c(2, 4, 8)
values %in% requested_ids
#> [1] FALSE  TRUE FALSE  TRUE FALSE FALSE

1.5 Functions and help

Functions are objects. A function receives arguments, performs a focused task, and returns its final evaluated expression unless return() is used.

center <- function(x, na.rm = FALSE) {
  x - mean(x, na.rm = na.rm)
}

center(c(2, 4, 6))
#> [1] -2  0  2

Inspect a function’s interface with args() and open its documentation with help() during an interactive session.

args(mean)
#> function (x, ...) 
#> NULL

1.6 Paths and temporary files

Prefer project-relative paths. Avoid embedding a personal absolute path or calling setwd() inside reusable analysis code.

temporary_path <- tempfile(fileext = ".txt")
writeLines(c("first row", "second row"), temporary_path)
readLines(temporary_path)
#> [1] "first row"  "second row"
unlink(temporary_path)

tempfile() makes the example portable and prevents it from leaving a file in the repository.

1.7 Interview checkpoints

  • Explain the difference between class() and typeof().
  • Describe vector coercion and give an example of accidental coercion.
  • Explain why is.na(x) is required instead of x == NA.
  • Distinguish & from && and | from ||.
  • Explain why project-relative paths are safer than setwd().