R Basics: Vectors and Types

· 12 min read · beginner
vectors types r-basics atomic-types
Part 2 of the r-fundamentals series

Vectors are the most fundamental data structure in R. Unlike many other programming languages, everything in R is a vector—even a single value is technically a vector of length one. Understanding vectors and their types is essential for writing effective R code.

This tutorial covers creating vectors, understanding atomic types, performing operations, and managing type coercion.

What Are Vectors?

A vector is an ordered collection of values of the same type. R stores vectors efficiently in memory and provides vectorized operations that work on entire vectors at once.

Creating Vectors with c()

The c() function (combine) creates vectors by joining values together:

# Numeric vector
numbers <- c(1, 2, 3, 4, 5)
numbers
# [1] 1 2 3 4 5

# Character vector
names <- c("Alice", "Bob", "Charlie")
names
# [1] "Alice"   "Bob"     "Charlie"

# Logical vector
flags <- c(TRUE, FALSE, TRUE)
flags
# [1]  TRUE FALSE  TRUE

Checking Vector Properties

R provides functions to inspect vectors:

# Length of a vector
length(numbers)
# [1] 5

# Check if it's a vector
is.vector(numbers)
# [1] TRUE

Atomic Types in R

R has six atomic vector types. The four most common are:

Numeric

The default type for numbers. R uses double-precision floating-point arithmetic:

# Numeric (double) is the default
x <- 3.14
typeof(x)
# [1] "double"

y <- c(1.5, 2.5, 3.5)
typeof(y)
# [1] "double"

Integer

Whole numbers, created with the L suffix:

# Create integer with L suffix
whole <- c(1L, 2L, 3L)
typeof(whole)
# [1] "integer"

# Also from sequences
seq_int <- 1:5
typeof(seq_int)
# [1] "integer"

Character

Text strings, always wrapped in quotes:

greeting <- "Hello, R!"
typeof(greeting)
# [1] "character"

words <- c("one", "two", "three")
typeof(words)
# [1] "character"

Logical

Boolean values TRUE and FALSE:

is_active <- c(TRUE, FALSE, TRUE, FALSE)
typeof(is_active)
# [1] "logical"

# Can also use T and F (not recommended)

Creating Vectors: Beyond c()

seq() for Sequences

Create sequences with regular intervals:

# Sequence from 1 to 10
1:10
# [1]  1  2  3  4  5  6  7  8  9 10

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

seq(0, 1, length.out = 5)
# [1] 0.00 0.25 0.50 0.75 1.00

rep() for Repeating Values

Repeat values to fill vectors:

# Repeat single value
rep(1, times = 5)
# [1] 1 1 1 1 1

# Repeat each element
rep(c(1, 2), each = 3)
# [1] 1 1 1 2 2 2

# Repeat entire vector
rep(c(1, 2), times = 3)
# [1] 1 2 1 2 1 2

Vector Operations

One of R’s strengths is vectorized operations:

# Arithmetic operations
c(1, 2, 3) + c(4, 5, 6)
# [1] 5 7 9

c(10, 20, 30) / c(2, 4, 5)
# [1] 5 5 6

# Recycling: shorter vectors are recycled
c(1, 2, 3, 4) + c(1, 2)
# [1] 2 4 4 6
# Warning: longer object length not a multiple of shorter

Recycling with Caution

R recycles shorter vectors but may produce unexpected results:

# What you might expect
c(1, 2, 3) + c(1, 2)
# [1] 2 4 4 (1+1, 2+2, 3+1)

# Always use vectors of equal length for clarity

Checking and Converting Types

Type Checking Functions

x <- c(1, 2, 3)

is.numeric(x)
# [1] TRUE

is.integer(x)
# [1] FALSE (defaults to double)

is.character(x)
# [1] FALSE

# To create integer
y <- c(1L, 2L, 3L)
is.integer(y)
# [1] TRUE

Type Conversion Functions

Convert between types with as.*() functions:

# Numeric to character
as.character(c(1, 2, 3))
# [1] "1" "2" "3"

# Character to numeric
as.numeric(c("1", "2", "3"))
# [1] 1 2 3

# Numeric to logical (0 = FALSE, non-zero = TRUE)
as.logical(c(0, 1, 2, -5))
# [1] FALSE  TRUE  TRUE  TRUE

# Character to logical
as.logical(c("TRUE", "FALSE", "true"))
# [1]  TRUE FALSE    NA

Implicit Type Coercion

When mixing types, R automatically coerces to the “highest” type:

# Numeric + character = character
c(1, "two", 3)
# [1] "1"  "two" "3"

# Logical + numeric = numeric
c(TRUE, 2, 3)
# [1] 1 2 3

# Order: logical → integer → double → character

Common Gotchas

Floating Point Comparison

# This might surprise you
0.1 + 0.2 == 0.3
# [1] FALSE

# Use near-equality
all.equal(0.1 + 0.2, 0.3)
# [1] TRUE

NA Values

NA represents missing values and has its own type:

# NA is typelogical by default
typeof(NA)
# [1] "logical"

# Check for NA
x <- c(1, 2, NA, 4)
is.na(x)
# [1] FALSE FALSE  TRUE FALSE

# NA in operations propagates
sum(c(1, 2, NA, 4))
# [1] NA

# Use na.rm = TRUE
sum(c(1, 2, NA, 4), na.rm = TRUE)
# [1] 7

Working with Vectors in Practice

Subsetting Vectors

Access elements using square brackets:

x <- c("a", "b", "c", "d", "e")

# By position
x[1]
# [1] "a"

x[c(1, 3)]
# [1] "a" "c"

# Negative indices remove elements
x[-1]
# [1] "b" "c" "d" "e"

# With logical vector
x[c(TRUE, FALSE, TRUE, FALSE, TRUE)]
# [1] "a" "c" "e"

Naming Vector Elements

# Create named vector
scores <- c(Alice = 95, Bob = 87, Charlie = 92)
scores
#    Alice      Bob Charlie 
#       95       87       92 

# Access by name
scores["Alice"]
# Alice 
#     95

names(scores)
# [1] "Alice"   "Bob"     "Charlie"

Summary

  • Vectors are R’s fundamental data structure—collections of values of the same type
  • The four main atomic types are: numeric, integer, character, and logical
  • Use c(), seq(), and rep() to create vectors
  • Vectorized operations work on entire vectors, making R efficient
  • Type checking: is.*() functions; conversion: as.*() functions
  • R coerces types implicitly when needed—understand the hierarchy

Next Steps

Now that you understand vectors, continue with the next tutorial in the r-fundamentals series: Data Frames and Tibbles, where you’ll learn how to work with rectangular data.

Practice what you learned:

# Try creating vectors of different types
numeric_vec <- c(1.5, 2.5, 3.5)
integer_vec <- c(1L, 2L, 3L)
char_vec <- c("apple", "banana", "cherry")
logical_vec <- c(TRUE, FALSE, TRUE)

# Check their types
sapply(list(numeric_vec, integer_vec, char_vec, logical_vec), typeof)