1.4 Introduction to R Concepts

DATA 412/612 · Week 1 · PDF · Source (.qmd)

Data types, data structures, indexing, functions, and special values.

1. Values and Objects

R works with values. For example:

10
## [1] 10
3.14
## [1] 3.14
"Hello"
## [1] "Hello"
TRUE
## [1] TRUE

We can store a value in an object using the assignment operator <-:

x <- 10
name <- "John"
passed <- TRUE

Anything after # on a line is a comment. R ignores it:

x <- 10   # store the number 10 in x

In this course we use <- for assignment. We use = for named function arguments, which we will meet shortly.

We can then use these objects later:

x
## [1] 10
name
## [1] "John"
passed
## [1] TRUE

2. Basic Data Types

Some of the most common data types in R are:

Type Examples Description

Numeric 5, 3.14, -10 Numbers

Integer 5L, 10L Whole numbers explicitly stored as integers

Character "Hello", "John" Text

Logical TRUE, FALSE Boolean values

Complex 2 + 3i Complex numbers

Examples:

x <- 10
y <- "Hello"
z <- TRUE

We can investigate objects using several functions:

typeof(x)
## [1] "double"
class(x)
## [1] "numeric"
mode(x)
## [1] "numeric"
length(x)
## [1] 1
str(x)
##  num 10

For example:

typeof(10)
## [1] "double"
# "double"

typeof("Hello")
## [1] "character"
# "character"

typeof(TRUE)
## [1] "logical"
# "logical"

Numeric vs. Integer

By default, R stores ordinary numbers as doubles:

typeof(5)
## [1] "double"
# "double"

To explicitly create an integer, add L:

typeof(5L)
## [1] "integer"
# "integer"

Both are considered numeric:

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

is.numeric(5L)
## [1] TRUE
# TRUE

Useful type-checking functions include:

is.numeric()
## Error in `is.numeric()`:
## ! 0 arguments passed to 'is.numeric' which requires 1
is.integer()
## Error in `is.integer()`:
## ! 0 arguments passed to 'is.integer' which requires 1
is.double()
## Error in `is.double()`:
## ! 0 arguments passed to 'is.double' which requires 1
is.character()
## Error in `is.character()`:
## ! 0 arguments passed to 'is.character' which requires 1
is.logical()
## Error in `is.logical()`:
## ! 0 arguments passed to 'is.logical' which requires 1
is.complex()
## Error in `is.complex()`:
## ! 0 arguments passed to 'is.complex' which requires 1

R also provides conversion functions:

as.numeric()
## numeric(0)
as.integer()
## integer(0)
as.character()
## character(0)
as.logical()
## logical(0)
as.complex()
## complex(0)

For example:

as.character(25)
## [1] "25"
# "25"

as.numeric("25")
## [1] 25
# 25

as.logical(1)
## [1] TRUE
# TRUE

3. Vectors

A vector is one of the most fundamental data structures in R.

A vector contains a sequence of values, normally of the same basic type.

We use c() (“combine”) to create a vector:

x <- c(10, 20, 30, 40)

x
## [1] 10 20 30 40
# [1] 10 20 30 40

The vector contains four elements:

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

We can create vectors of different types:

numbers <- c(10, 20, 30)

names <- c("John", "Sara", "David")

answers <- c(TRUE, FALSE, TRUE)

Useful functions for exploring vectors include:

length(x)
## [1] 4
typeof(x)
## [1] "double"
class(x)
## [1] "numeric"
str(x)
##  num [1:4] 10 20 30 40
head(x)
## [1] 10 20 30 40
tail(x)
## [1] 10 20 30 40
unique(x)
## [1] 10 20 30 40
duplicated(x)
## [1] FALSE FALSE FALSE FALSE
sort(x)
## [1] 10 20 30 40
rev(x)
## [1] 40 30 20 10

Vectorized arithmetic

R applies arithmetic to every element of a vector:

x <- c(10, 20, 30, 40)

x * 2
## [1] 20 40 60 80
# 20 40 60 80

x + 1
## [1] 11 21 31 41
# 11 21 31 41

x / 10
## [1] 1 2 3 4
# 1 2 3 4

If two vectors have different lengths, R recycles the shorter one. We will look at this more carefully in the lab.

Useful numerical summaries include:

sum(x)
## [1] 100
mean(x)
## [1] 25
median(x)
## [1] 25
min(x)
## [1] 10
max(x)
## [1] 40
range(x)
## [1] 10 40
var(x)
## [1] 166.6667
sd(x)
## [1] 12.90994

4. What Happens When Types Are Mixed?

An atomic vector normally contains one type.

Consider:

x <- c(1, 2, "hello")

R cannot keep some elements numeric and one character in the same atomic vector, so it converts them to a common type:

x
## [1] "1"     "2"     "hello"
# "1" "2" "hello"

typeof(x)
## [1] "character"
# "character"

This automatic conversion is called coercion.

Another example:

c(TRUE, 5)
## [1] 1 5

R converts TRUE to a numeric value:

# 1 5

A useful simplified coercion hierarchy is:

logical → integer → double → character

  1. Lists What if we actually want one object to contain values of different types?

We can use a list.

A list is a data structure that can contain elements of different types and even different structures.

x <- list(
  25,
  "John",
  TRUE
)

x
## [[1]]
## [1] 25
## 
## [[2]]
## [1] "John"
## 
## [[3]]
## [1] TRUE

Unlike an atomic vector, the elements do not need to have the same type.

We can also name the elements:

student <- list(
  name = "John",
  age = 25,
  grades = c(90, 85, 95),
  passed = TRUE
)

Useful functions include:

length(student)
## [1] 4
names(student)
## [1] "name"   "age"    "grades" "passed"
str(student)
## List of 4
##  $ name  : chr "John"
##  $ age   : num 25
##  $ grades: num [1:3] 90 85 95
##  $ passed: logi TRUE
is.list(student)
## [1] TRUE

Lists are extremely flexible: an element of a list can itself be a vector, matrix, data frame, or even another list.


6. Other Important Data Structures

Matrix

A matrix organizes values into rows and columns:

x <- matrix(1:6, nrow = 2)

x
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6

Useful functions:

dim(x)
## [1] 2 3
nrow(x)
## [1] 2
ncol(x)
## [1] 3
rownames(x)
## NULL
colnames(x)
## NULL
is.matrix(x)
## [1] TRUE

Data Frame

A data frame is one of the most important structures for data analysis.

students <- data.frame(
  name = c("John", "Sara", "David"),
  grade = c(90, 85, 95),
  passed = c(TRUE, TRUE, TRUE)
)

Each column can have a different data type.

Useful functions include:

dim(students)
## [1] 3 3
nrow(students)
## [1] 3
ncol(students)
## [1] 3
names(students)
## [1] "name"   "grade"  "passed"
colnames(students)
## [1] "name"   "grade"  "passed"
rownames(students)
## [1] "1" "2" "3"
head(students)
##    name grade passed
## 1  John    90   TRUE
## 2  Sara    85   TRUE
## 3 David    95   TRUE
tail(students)
##    name grade passed
## 1  John    90   TRUE
## 2  Sara    85   TRUE
## 3 David    95   TRUE
str(students)
## 'data.frame':    3 obs. of  3 variables:
##  $ name  : chr  "John" "Sara" "David"
##  $ grade : num  90 85 95
##  $ passed: logi  TRUE TRUE TRUE
summary(students)
##         name       grade       passed       
##  Length   :3   Min.   :85.0   Mode:logical  
##  N.unique :3   1st Qu.:87.5   TRUE:3        
##  N.blank  :0   Median :90.0                 
##  Min.nchar:4   Mean   :90.0                 
##  Max.nchar:5   3rd Qu.:92.5                 
##                Max.   :95.0
is.data.frame(students)
## [1] TRUE

View(students) opens the data in an RStudio tab. That is often easier than printing a large table in the console.

A tibble is the tidyverse version of a data frame. Printing is cleaner, and character columns stay character instead of being turned into factors. readr::read_csv() returns a tibble.

library(tidyverse)

as_tibble(students)
## # A tibble: 3 × 3
##   name  grade passed
##   <chr> <dbl> <lgl> 
## 1 John     90 TRUE  
## 2 Sara     85 TRUE  
## 3 David    95 TRUE
tibble(
  name = c("John", "Sara", "David"),
  grade = c(90, 85, 95)
)
## # A tibble: 3 × 2
##   name  grade
##   <chr> <dbl>
## 1 John     90
## 2 Sara     85
## 3 David    95

A tibble is still a data frame. is.data.frame() is TRUE for both.

Factor

A factor is commonly used to represent categorical data:

gender <- factor(c("Male", "Female", "Female", "Male"))

Useful functions:

levels(gender)
## [1] "Female" "Male"
nlevels(gender)
## [1] 2
table(gender)
## gender
## Female   Male 
##      2      2
is.factor(gender)
## [1] TRUE

7. Comparisons and Logical Operators

A logical value is TRUE or FALSE. Comparison operators produce logicals:

13 > 4
## [1] TRUE
# TRUE

13 < 4
## [1] FALSE
# FALSE

4 >= 4
## [1] TRUE
# TRUE

4 == 4
## [1] TRUE
# TRUE

13 != 4
## [1] TRUE
# TRUE

Use == to test equality. A single = is assignment or a named argument, not a comparison.

The operators are vectorized:

x <- c(1, 2, 3, 4)
y <- c(1, 4, 4, 4)

x == y
## [1]  TRUE FALSE FALSE  TRUE
# TRUE FALSE FALSE TRUE

x < y
## [1] FALSE  TRUE  TRUE FALSE
# FALSE TRUE TRUE FALSE

Combine conditions with & (and) and | (or):

TRUE & FALSE
## [1] FALSE
# FALSE

TRUE | FALSE
## [1] TRUE
# TRUE

(x < 3) & (y >= 4)
## [1] FALSE  TRUE FALSE FALSE
# FALSE TRUE FALSE FALSE

(x < 3) | (y >= 4)
## [1] TRUE TRUE TRUE TRUE
# TRUE TRUE TRUE TRUE

! negates a logical. xor(a, b) is true when exactly one of a or b is true.

A comparison is the usual way to subset a vector:

x <- 1:5
x[x < 3]
## [1] 1 2
# 1 2

%% is useful here. n %% 3 == 0 is true when n is a multiple of 3.


8. Indexing

We often need part of an object, not the entire object.

The main indexing operator in R is [ ].

Vectors

x <- c(10, 20, 30, 40)

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

x[c(1, 4)]
## [1] 10 40
# 10 40

x[2:3]
## [1] 20 30
# 20 30

Positions in R start at 1, not 0.

Negative indices drop elements:

x[-1]
## [1] 20 30 40
# 20 30 40

We can also index with a logical vector:

x[c(TRUE, FALSE, TRUE, FALSE)]
## [1] 10 30
# 10 30

A common pattern is to keep the values that satisfy a condition:

x[x > 20]
## [1] 30 40
# 30 40

If the elements have names, we can index by name:

scores <- c(midterm = 90, final = 85)

scores["final"]
## final 
##    85
# 85

Lists

For a list, [ and [[ do different things.

student <- list(
  name = "John",
  age = 25,
  grades = c(90, 85, 95)
)

student[1]
## $name
## [1] "John"

This returns a list of length 1.

student[[1]]
## [1] "John"
# "John"

This returns the element itself.

The $ operator is a convenient way to extract a named element:

student$name
## [1] "John"
# "John"

A useful way to remember the difference is:

[ → a piece of the list, still a list [[ → the element itself $ → a named element

Matrices A matrix is indexed by row and column:

x <- matrix(1:6, nrow = 2)

x[1, 2]
## [1] 3
x[1, ]
## [1] 1 3 5
x[, 2]
## [1] 3 4

x[1, ] is the first row. x[, 2] is the second column.

Data Frames

A data frame can be indexed like a matrix and also like a list.

students$grade
## [1] 90 85 95
students[1, ]
##   name grade passed
## 1 John    90   TRUE
students[, "grade"]
## [1] 90 85 95

students$grade extracts the grade column as a vector.

students[1, ] extracts the first row, still as a data frame.

An important detail:

students[, "grade"]
## [1] 90 85 95
# a vector

students[, "grade", drop = FALSE]
##   grade
## 1    90
## 2    85
## 3    95
# a data frame with one column

By default, extracting a single column drops the data-frame structure.


9. Functions

A function performs a particular task.

The general form is:

function_name(arguments)
## Error in `function_name()`:
## ! could not find function "function_name"

For example:

sqrt(16)
## [1] 4
# 4

Here:

  • sqrt is the function name.
  • 16 is an argument.
  • 4 is the returned result.

Another example:

round(3.14159, digits = 2)
## [1] 3.14
# 3.14

This function has multiple arguments.

You can read the documentation of a function using:

?round

or:

help(round)

You can also inspect the arguments:

args(round)
## function (x, digits = 0, ...) 
## NULL

10. Positional and Named Arguments

Consider:

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

The arguments have names:

from = 1 to = 10 by = 2

Because R can match arguments by their positions, we can also write:

seq(1, 10, 2)
## [1] 1 3 5 7 9

Both produce:

# 1 3 5 7 9

Using argument names often makes code easier to understand.

A useful distinction is:

x <- 10                      # assignment: store a value

round(3.14159, digits = 2)   # = gives a name to an argument
## [1] 3.14

<- creates an object. = inside a function call names an argument.


11. Default Arguments

Functions can provide default values for arguments.

For example:

round(3.14159)
## [1] 3
# 3

We did not specify digits, so R uses its default.

Compare:

round(3.14159, digits = 2)
## [1] 3.14
# 3.14

The help page of a function shows its available arguments and their defaults:

?round

12. The seq() Function

seq() is a useful example for understanding function arguments.

It creates sequences.

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

Here:

from = 1 starting value to = 10 ending value by = 2 step size

We can also specify the desired number of elements:

seq(from = 1, to = 10, length.out = 4)
## [1]  1  4  7 10
# 1 4 7 10

So there are different ways to tell seq() what sequence we want.

Some arguments in seq() have a default value of NULL. This brings us to several important special values in R.


13. Special Values: NA, NaN, Inf, and NULL

R has several special values that have different meanings:

Value Meaning Example

NA Missing or unknown value c(10, NA, 20)

NaN Undefined numerical result (“Not a Number”) 0/0

Inf Infinity 1/0

-Inf Negative infinity -1/0

NULL Absence of a value x <- NULL

A simple way to remember them:

NA = I don’t know the value.

NaN = The numerical calculation is undefined.

Inf = The numerical result is infinite.

NULL = There is no value at all.


14. Detecting Special Values: The is.*() Family

Consider:

x <- c(NA, NaN, Inf, 5)

Now apply several functions:

is.na(x)
## [1]  TRUE  TRUE FALSE FALSE
# TRUE TRUE FALSE FALSE

is.nan(x)
## [1] FALSE  TRUE FALSE FALSE
# FALSE TRUE FALSE FALSE

is.infinite(x)
## [1] FALSE FALSE  TRUE FALSE
# FALSE FALSE TRUE FALSE

is.finite(x)
## [1] FALSE FALSE FALSE  TRUE
# FALSE FALSE FALSE TRUE

The results can be summarized as:

Value is.na() is.nan() is.infinite() is.finite()

NA TRUE FALSE FALSE FALSE

NaN TRUE TRUE FALSE FALSE

Inf FALSE FALSE TRUE FALSE

5 FALSE FALSE FALSE TRUE

An important observation is:

is.na(NaN)
## [1] TRUE
# TRUE

is.nan(NA)
## [1] FALSE
# FALSE

Thus, NaN is also considered a missing value by is.na().


15. Why Is NULL Different?

Consider:

x <- c(NA, NaN, Inf, NULL)

x
## [1]  NA NaN Inf
# NA NaN Inf

Although we supplied four things:

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

Why?

Because NULL represents the absence of a value. It contributes no element to the vector.

Compare:

length(NA)
## [1] 1
# 1

length(NaN)
## [1] 1
# 1

length(Inf)
## [1] 1
# 1

length(NULL)
## [1] 0
# 0

Therefore:

NA is a missing value; NULL is no value.

We test for NULL using:

is.null(NULL)
## [1] TRUE
# TRUE

16. Missing Values in Real Data

Suppose we have:

grades <- c(90, 85, NA, 95)

Then:

mean(grades)
## [1] NA
# NA

Because one grade is unknown, R cannot calculate the ordinary mean.

Many R functions provide an na.rm argument:

mean(grades, na.rm = TRUE)
## [1] 90
# 90

na.rm means:

NA remove

Other useful functions include:

is.na(grades)
## [1] FALSE FALSE  TRUE FALSE

to identify missing values,

anyNA(grades)
## [1] TRUE

to determine whether there are any missing values,

and:

na.omit(grades)
## [1] 90 85 95
## attr(,"na.action")
## [1] 3
## attr(,"class")
## [1] "omit"

to remove observations containing missing values.

For data frames, another important function is:

complete.cases()
## Error in `complete.cases()`:
## ! no input has determined the number of cases

For example:

students <- data.frame(
  grade = c(90, NA, 85),
  age = c(20, 21, NA)
)

complete.cases(students)
## [1]  TRUE FALSE FALSE
# TRUE FALSE FALSE

17. Useful is.*() Functions

R has a large family of functions beginning with is.. They ask questions about an object and usually return TRUE or FALSE.

Checking data types

is.numeric(x)
## [1] TRUE
is.integer(x)
## [1] FALSE
is.double(x)
## [1] TRUE
is.character(x)
## [1] FALSE
is.logical(x)
## [1] FALSE
is.complex(x)
## [1] FALSE

Checking data structures

is.vector(x)
## [1] TRUE
is.list(x)
## [1] FALSE
is.matrix(x)
## [1] FALSE
is.array(x)
## [1] FALSE
is.data.frame(x)
## [1] FALSE
is.factor(x)
## [1] FALSE

Checking special values

is.na(x)
## [1]  TRUE  TRUE FALSE
is.nan(x)
## [1] FALSE  TRUE FALSE
is.finite(x)
## [1] FALSE FALSE FALSE
is.infinite(x)
## [1] FALSE FALSE  TRUE
is.null(x)
## [1] FALSE

These functions make the naming convention easy to remember:

is.numeric(x)

asks:

“Is x numeric?”

and:

is.na(x)

asks:

“Is x missing?”


18. Useful as.*() Functions

The as.*() family usually attempts to convert an object.

as.numeric(x)
## [1]  NA NaN Inf
as.integer(x)
## [1] NA NA NA
as.double(x)
## [1]  NA NaN Inf
as.character(x)
## [1] NA    "NaN" "Inf"
as.logical(x)
## [1]   NA   NA TRUE
as.vector(x)
## [1]  NA NaN Inf
as.list(x)
## [[1]]
## [1] NA
## 
## [[2]]
## [1] NaN
## 
## [[3]]
## [1] Inf
as.matrix(x)
##      [,1]
## [1,]   NA
## [2,]  NaN
## [3,]  Inf
as.data.frame(x)
##     x
## 1  NA
## 2 NaN
## 3 Inf
as.factor(x)
## [1] <NA> NaN  Inf 
## Levels: Inf NaN

This gives us a useful distinction:

is.*() → asks what something is

as.*() → tries to convert something

For example:

x <- "25"

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

as.numeric(x)
## [1] 25
# 25

19. A Useful Family of Functions to Remember

At this stage, students should recognize several families of functions.

Investigating an object

typeof()
## Error in `typeof()`:
## ! argument "x" is missing, with no default
class()
## Error in `class()`:
## ! 0 arguments passed to 'class' which requires 1
mode()
## Error in `mode()`:
## ! argument "x" is missing, with no default
str()
## Error in `str.default()`:
## ! argument "object" is missing, with no default
length()
## Error in `length()`:
## ! 0 arguments passed to 'length' which requires 1
attributes()
## Error in `attributes()`:
## ! 0 arguments passed to 'attributes' which requires 1
names()
## Error in `names()`:
## ! 0 arguments passed to 'names' which requires 1
dim()
## Error in `dim()`:
## ! 0 arguments passed to 'dim' which requires 1

Asking what an object is

is.numeric()
## Error in `is.numeric()`:
## ! 0 arguments passed to 'is.numeric' which requires 1
is.integer()
## Error in `is.integer()`:
## ! 0 arguments passed to 'is.integer' which requires 1
is.character()
## Error in `is.character()`:
## ! 0 arguments passed to 'is.character' which requires 1
is.logical()
## Error in `is.logical()`:
## ! 0 arguments passed to 'is.logical' which requires 1
is.vector()
## Error in `is.vector()`:
## ! argument "x" is missing, with no default
is.list()
## Error in `is.list()`:
## ! 0 arguments passed to 'is.list' which requires 1
is.matrix()
## Error in `is.matrix()`:
## ! 0 arguments passed to 'is.matrix' which requires 1
is.data.frame()
## Error in `is.data.frame()`:
## ! argument "x" is missing, with no default
is.factor()
## Error in `is.factor()`:
## ! argument "x" is missing, with no default
is.na()
## Error in `is.na()`:
## ! 0 arguments passed to 'is.na' which requires 1
is.nan()
## Error in `is.nan()`:
## ! 0 arguments passed to 'is.nan' which requires 1
is.infinite()
## Error in `is.infinite()`:
## ! 0 arguments passed to 'is.infinite' which requires 1
is.finite()
## Error in `is.finite()`:
## ! 0 arguments passed to 'is.finite' which requires 1
is.null()
## Error in `is.null()`:
## ! 0 arguments passed to 'is.null' which requires 1

Converting objects

as.numeric()
## numeric(0)
as.integer()
## integer(0)
as.character()
## character(0)
as.logical()
## logical(0)
as.vector()
## Error in `as.vector()`:
## ! argument "x" is missing, with no default
as.list()
## Error in `as.list.default()`:
## ! argument "x" is missing, with no default
as.matrix()
## Error in `as.matrix.default()`:
## ! argument "x" is missing, with no default
as.data.frame()
## Error in `as.data.frame()`:
## ! argument "x" is missing, with no default
as.factor()
## Error in `as.factor()`:
## ! argument "x" is missing, with no default

Indexing

x[1]
## [1] "25"
x[1:3]
## [1] "25" NA   NA
x[-1]
## character(0)
x[x > 20]
## [1] "25"
x["name"]
## [1] NA
student[[1]]
## [1] "John"
student$name
## [1] "John"
m[1, 2]
## Error:
## ! object 'm' not found
df[1, ]
## Error in `df[1, ]`:
## ! object of type 'closure' is not subsettable
df$grade
## Error in `df$grade`:
## ! object of type 'closure' is not subsettable

Basic vector operations

c()
## NULL
length()
## Error in `length()`:
## ! 0 arguments passed to 'length' which requires 1
seq()
## [1] 1
rep()
## NULL
sort()
## Error in `sort.default()`:
## ! argument "x" is missing, with no default
rev()
## Error in `rev.default()`:
## ! argument "x" is missing, with no default
unique()
## Error in `unique.default()`:
## ! argument "x" is missing, with no default
duplicated()
## Error in `duplicated.default()`:
## ! argument "x" is missing, with no default

Basic numerical summaries

sum()
## [1] 0
mean()
## Error in `mean.default()`:
## ! argument "x" is missing, with no default
median()
## Error in `median.default()`:
## ! argument "x" is missing, with no default
min()
## [1] Inf
max()
## [1] -Inf
range()
## [1]  Inf -Inf
var()
## Error in `var()`:
## ! argument "x" is missing, with no default
sd()
## Error in `sd()`:
## ! argument "x" is missing, with no default
summary()
## Error in `summary.default()`:
## ! argument "object" is missing, with no default

Missing-data functions

is.na()
## Error in `is.na()`:
## ! 0 arguments passed to 'is.na' which requires 1
anyNA()
## Error in `anyNA()`:
## ! anyNA takes 1 or 2 arguments
na.omit()
## Error in `na.omit.default()`:
## ! argument "object" is missing, with no default
complete.cases()
## Error in `complete.cases()`:
## ! no input has determined the number of cases

and the commonly encountered argument:

na.rm = TRUE

20. The Big Picture

The concepts introduced so far fit together:

VALUES │ ├── Numeric ├── Character ├── Logical └── Other types │ ▼ OBJECTS │ ▼ DATA STRUCTURES │ ├── Vector ├── List ├── Matrix ├── Data Frame └── Factor │ ▼ INDEXING │ ├── [ → select a part ├── [[ → extract an element └── $ → extract a named element │ ▼ FUNCTIONS │ ├── Function name ├── Arguments ├── Named/positional arguments └── Default arguments │ ▼ SPECIAL VALUES │ ├── NA → missing/unknown value ├── NaN → undefined numerical result ├── Inf → infinity └── NULL → absence of a value

Three function families are particularly useful to remember:

is.() → What is it? as.() → Convert it ? → How does it work?

For example:

is.numeric(x)
## [1] FALSE
as.numeric(x)
## [1] 25
?as.numeric

These ideas form the foundation for working with data in R.