R Vectors Exercises: 12 Hands-On Problems with Step-by-Step Answers

Twelve focused exercises on R's most fundamental data structure. You will create vectors, coerce types, index by position, name and logical mask, do vectorised arithmetic, and avoid the two recycling traps that catch almost every beginner. Every problem is runnable right here in the page.

The single most important thing to understand in R is that almost everything is a vector. Scalars are length-one vectors. Data frame columns are vectors. Function arguments are often vectors. Mastering vectors is the one investment that pays off in every other part of R.

Work through the exercises in order. The code blocks share state across the whole page, so variables you create in Exercise 1 are still available in Exercise 12.

Section 1, Creating and inspecting vectors

Exercise 1. Four ways to create a vector

Create the same numeric vector 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 in four different ways: with c(), with :, with seq(), and with seq_len(). Confirm they are equal with identical().

RExercise: Build 1:10 four ways
# Your attempt here

  
Solution
RFour ways to build 1:10 solution
v1 <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) v2 <- 1:10 v3 <- seq(1, 10, by = 1) v4 <- seq_len(10) identical(v2, v4) # TRUE, both are integer identical(v1, v3) # TRUE, both are double identical(v1, v2) # FALSE, one is double, one is integer

  

1:10 and seq_len(10) both produce integer vectors. c(1, 2, ...) and seq(1, 10, by = 1) produce double vectors. The values print the same but the type differs.

Exercise 2. Type coercion in c()

Predict the type of each of these vectors, then check with typeof():

RPredict the type of each vector
c(1, 2, 3) c(1L, 2L, 3L) c(1, 2L, 3) c(1, "2", 3) c(1, TRUE, 3)

  
RExercise: Predict coercion types
# Your attempt here

  
Solution
RCoercion types solution
typeof(c(1, 2, 3)) # "double" typeof(c(1L, 2L, 3L)) # "integer" typeof(c(1, 2L, 3)) # "double", integer promoted to double typeof(c(1, "2", 3)) # "character", everything becomes character typeof(c(1, TRUE, 3)) # "double", logical promoted to double

  

The coercion hierarchy is logical → integer → double → character. c() picks the most general type present.

Exercise 3. Length, head, tail

Create x <- seq(5, 100, by = 5). Report its length, the first three values, and the last three values.

RExercise: Inspect seq(5, 100, 5)
# Your attempt here

  
Solution
RSequence inspection solution
x <- seq(5, 100, by = 5) length(x) # 20 head(x, 3) # 5 10 15 tail(x, 3) # 90 95 100

  

Section 2, Indexing

Exercise 4. Positive and range indexing

From x (Exercise 3), extract the 1st, 5th and 10th elements in one call, and then the 11th through 15th elements as a contiguous slice.

RExercise: Positional and contiguous indexing
# Your attempt here

  
Solution
RPositional indexing solution
x[c(1, 5, 10)] # 5 25 50 x[11:15] # 55 60 65 70 75

  

A vector of indices inside [ ] picks those positions in the order given. Ranges are just vectors built with :.

Exercise 5. Negative indexing

From x, return everything except the last two elements. Do it two ways: with a negative index, and with head().

RExercise: Drop last two elements
# Your attempt here

  
Solution
RDrop last elements solution
x[-c(length(x) - 1, length(x))] # everything but last two head(x, -2) # same result, cleaner # head(x, -2) returns all but the last 2 elements. # Similarly, tail(x, -2) returns all but the first 2.

  

head() and tail() accept negative counts. This is the idiomatic way to drop trailing or leading elements.

Exercise 6. Logical indexing

Return the elements of x that are strictly greater than 30 and strictly less than 75.

RExercise: Filter by numeric range
# Your attempt here

  
Solution
RRange filter solution
x[x > 30 & x < 75] # 35 40 45 50 55 60 65 70 # Step-by-step: x > 30 # logical vector x < 75 # logical vector (x > 30) & (x < 75) # element-wise AND x[(x > 30) & (x < 75)] # filter

  

Use & for element-wise AND and | for element-wise OR. The double forms && and || are for single-value logic in if statements and should not be used for vector filtering.

Exercise 7. Named vectors

Create a named vector of the populations (in millions) of five countries:

RBuild named population vector
pop <- c(USA = 331, China = 1412, India = 1417, Brazil = 215, Nigeria = 223)

  

Return India's population by name, the values for USA and Nigeria in one call, and the names of all countries with population greater than 300 million.

RExercise: Named vector indexing
# Your attempt here

  
Solution
RNamed indexing solution
pop <- c(USA = 331, China = 1412, India = 1417, Brazil = 215, Nigeria = 223) pop["India"] # India: 1417 pop[c("USA", "Nigeria")] # USA: 331, Nigeria: 223 names(pop)[pop > 300] # "USA" "China" "India"

  

Note the last one: you apply the logical index to names(pop), not to pop itself, because you want the names back, not the values.

Section 3, Arithmetic, recycling, and summaries

Exercise 8. Vectorised arithmetic

Create a <- 1:5 and b <- 6:10. Compute a + b, a * b, a^b, and the dot product.

RExercise: Arithmetic and dot product
# Your attempt here

  
Solution
RArithmetic and dot product solution
a <- 1:5 b <- 6:10 a + b # 7 9 11 13 15 a * b # 6 14 24 36 50 a^b # 1 128 6561 262144 9765625 sum(a * b) # 130, the dot product

  

R has no special dot-product operator (unlike NumPy). sum(a * b) is idiomatic and fast.

Exercise 9. Recycling, the safe case and the trap

Predict the output of each of these. Run them and read the warning on the second one.

RPredict recycling outputs
c(1, 2, 3, 4) * c(10, 100) c(1, 2, 3, 4, 5) * c(10, 100)

  
RExercise: Predict recycling results
# Your attempt here

  
Solution
RRecycling solution
c(1, 2, 3, 4) * c(10, 100) # 10 200 30 400, clean recycling, length 2 divides length 4 c(1, 2, 3, 4, 5) * c(10, 100) # Warning message: # longer object length is not a multiple of shorter object length # 10 200 30 400 50

  

R recycles the shorter vector to match the longer. When lengths divide cleanly, no warning. When they do not, R still recycles but warns, and that is almost always a bug in your code. Treat the warning as an error until you have investigated.

Exercise 10. Summary functions

Using pop from Exercise 7, compute the total population, the mean, the median, the country with the largest population (by name), and the country with the smallest (by name).

RExercise: Summaries on pop
# Your attempt here

  
Solution
RSummaries on pop solution
sum(pop) # 3598 (million) mean(pop) # 719.6 median(pop) # 331 names(pop)[which.max(pop)] # "India" names(pop)[which.min(pop)] # "Brazil"

  

which.max() and which.min() return the index of the max/min, which you then apply to names(pop) to get the label.

Section 4, Missing values and reordering

Exercise 11. NAs and counting

Create v <- c(5, NA, 3, 8, NA, 1, 6, NA, 9). Count the NAs, compute the mean ignoring NAs, and return the vector with NAs replaced by 0.

RExercise: Count, mean, and fill NAs
# Your attempt here

  
Solution
RNA handling solution
v <- c(5, NA, 3, 8, NA, 1, 6, NA, 9) sum(is.na(v)) # 3 mean(v, na.rm = TRUE) # 5.333333 v_clean <- v v_clean[is.na(v_clean)] <- 0 v_clean # 5 0 3 8 0 1 6 0 9

  

is.na(v) returns a logical vector. You can use it to either count, filter, or assign into the NA positions.

Exercise 12. Sorting and ordering

From pop (Exercise 7), return (a) the populations sorted descending, and (b) the countries listed from smallest population to largest.

RExercise: Sort and order pop
# Your attempt here

  
Solution
RSort and order solution
sort(pop, decreasing = TRUE) # India 1417, China 1412, USA 331, Nigeria 223, Brazil 215 pop[order(pop)] # Brazil 215, Nigeria 223, USA 331, China 1412, India 1417

  

sort() reorders the values and keeps the names alongside. order() returns the indices that would produce the sorted order, use it when you need to reorder several parallel vectors (or a data frame) by one of them.

Summary

  • Vectors are R's fundamental data structure. Scalars are just length-one vectors.
  • c() promotes types upward: logical → integer → double → character.
  • Index with positive integers, negative integers, logicals, or names. Logical indexing is the most common in real analysis.
  • Arithmetic is vectorised element-wise. Recycling happens when lengths differ, silent when clean, warned otherwise.
  • Handle NAs with na.rm = TRUE or by masking with is.na().
  • Use sort() to reorder a single vector, order() to produce indices for reordering multiple parallel vectors.

References

Continue Learning