4 Data wrangling with R

Written by Keaka Farleigh on August 5th, 2025

Last updated by Keaka Farleigh on July 3rd, 2026

4.1 Purpose

This tutorial will give you an introduction to data wrangling. You will learn what it is and get some hands-on experience wrangling some data. I will assume that you have minimal experience with R and are a beginner user. Please read through the Introduction to R chapter or send me an email if you do not feel comfortable with this tutorial.

4.2 Learning objectives

  • Learn why data transformation and management is common.
  • Learn how to filter, sort, and summarize data.
  • Learn how to pivot data.

4.3 Files required for this pipeline

None!

4.4 Programs used in this pipeline

Install the tidyverse using the command below.

install.packages("tidyverse")

library(tidyverse)

4.5 Notes on this tutorial

The materials in this tutorial were originally developed as part of the Lambda bioinformatic workshop at Miami University by Dr. Tereza Jezkova and Dr. Alfredo Ascanio. These materials are now presented at Lambda and the Foundations in R workshop at the University of Virginia.

4.6 Overview

We will cover the basics of data wrangling before working through some examples!

4.7 What is data wrangling and why is it a common first step?

Have you ever opened a file from a collaborator or output from a program but it was not formatted as you expected? What did you do? Did you leave it as is, or did you modify the file so that it conformed to your expectations? If you modified the file, then you have already wrangled some data. Data wrangling is a fancy way of saying data processing, transformation, and cleaning to prepare it for analysis, presentation, or visualization. For many researchers and data scientists, data wrangling consumes a lot of time and is therefore a foundation tool for modern data analysis.

4.8 So how do I wrangle data?

Data wrangling can be performed in base R (without loading any packages) or using specially designed packages like dplyr or others in the tidyverse. We will walk through a few examples below.

4.9 Filtering data

Imagine you only want to retain specific rows in data. We will use the filter command from dplyr to select rows that satisfy a specific condition. In this case, we will use the iris dataset to only select data from the setosa species. I will provide a solution with dplyr and with base R.

# Get the data 
data(iris)

# dplyr solution
setosa_df <- iris %>% filter(Species == "setosa")

# base R solution
setosa_df2 <- iris[which(iris$Species == "setosa"),]

Notice that specialized packages like dplyr often provide a simplified line of code (relative to base R), even though they produce the same result. In the dplyr code, we are providing the iris data and telling R to only retain (filter) rows where the species is setosa. In the base R code, we are identifying which elements in the iris$Species column are setosa and then telling R to retain those rows by putting the which command before the comma.

Now you try

How would you filter for rows associated with virginica? Try it yourself, then reveal the code below.

Click to show solution

# dplyr solution
setosa_df <- iris %>% filter(Species == "virginica")

# base R solution
setosa_df2 <- iris[which(iris$Species == "virginica"),]

4.10 Sorting data

Another common task of data wrangling is sorting to understand which observations are the smallest or largest or even which ones are close together. Like filtering, there are multiple ways to do this and we will use dplyr and base R. Let’s sort our data by Petal.Width.

setosa_pw_ord <- setosa_df %>% arrange(Petal.Width)

setosa_pw_ord2 <- setosa_df2[order(setosa_df2$Petal.Width), ]

Again, the dplyr command is simpler than the base R command. We simply use the arrange command, while base R requires us to again identify the order of the rows that we want (order function) and then specify that row order by putting the order command before the comma.

Now you try

How would you sort by Petal.Length? Try it yourself, then reveal the code below.

Click to show solution
setosa_pl_ord <- setosa_df %>% arrange(Petal.Length)

setosa_pl_ord2 <- setosa_df2[order(setosa_df2$Petal.Length), ]

4.11 Summarize

Summarizing data is a key component of any analysis and often done during exploratory data analysis to identify any potential trends in our data. We will use the group_by function from dplyr to summarise the iris data by species to estimate the mean Petal.Length.

iris %>% group_by(Species) %>% 
  summarise(mean_PL = mean(Petal.Length)) %>%
  ungroup()

Here our command first groups the data by species. Then, we use the summarise and mean functions to calculate the mean Petal.Length for each group (species). Finally, as a best practice we ungroup the data so that we don’t influence any future analyses.

In base R this would have required us to split the data into three different object, take the mean within each of those objects, then put it back together.

Now you try

How would you summarize by Petal.Width? Try it yourself, then reveal the code below.

Click to show solution
iris %>% group_by(Species) %>% 
  summarise(mean_PL = mean(Petal.Width)) %>%
  ungroup()

4.12 Pivot

The last thing we will learn to do is pivot data. This means to transform the data from wide to long or long to wide format. Wide format means data where there are more columns than rows and long format means more rows than columns. Again, the tidyverse provides solutions for this, but we can also do it in base R. Let’s pivot our iris data. We will add a column named Ind and pivot the data to long format where each row represents an individual and one of its characteristics (e.g., Petal.Length, Petal.Width).

iris_long <- iris %>% 
    mutate(Ind = 1:150) %>%
    pivot_longer(cols = 1:4, names_to = "Variable", 
    values_to = "Value")

In this command we add the individual labels with mutate, then we pivot the data to long format with pivot_longer.

Now you try

Can you pivot the iris_long data frame to wide format? Hint, you can use the function pivot_wider. Try it yourself, then reveal the code below.

Click to show solution
iris_wide <- iris_long %>% 
  pivot_wider(names_from = Variable, values_from = Value)

We are done! As always, please reach out with any questions or suggestions.

4.13 References

R Core Team (2025). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/.

Wickham, H., François, R., Henry, L., Müller, K., & Vaughan, D. (2026). dplyr: A Grammar of Data Manipulation. R package version 1.2.1. https://dplyr.tidyverse.org

Wickham, H., et al. (2019). Welcome to the tidyverse. Journal of Open Source Software, 4(43), 1686. https://doi.org/10.21105/joss.01686