Data processing and visualisation in R

This tutorial introduces a simple workflow for turning raw observations into a clean table, a summary and a clear figure. It assumes that you have completed the R basics tutorial.

Learning outcomes

By the end of this tutorial, you should be able to:

  • keep raw data separate from derived results;
  • inspect and clean a dataset without editing the raw file;
  • filter and summarise observations; and
  • create and save a clear figure with ggplot2.

1. Organise your project

A simple project structure makes an analysis easier to understand and repeat:

project/
├── code/       # R scripts
├── data/       # original data; do not edit by hand
└── results/    # cleaned tables and figures

2. Load and inspect the data

The example below uses the iris dataset included with R, so no download is needed.

data(iris)

head(iris)
dim(iris)
names(iris)
str(iris)
summary(iris)
colSums(is.na(iris))

Before changing anything, confirm what one row represents, what each column means, which units are used and how missing values are recorded.

3. Select and clean observations

The following example creates a new object and leaves the original data unchanged.

clean_data <- subset(
  iris,
  !is.na(Sepal.Length) & Sepal.Length > 0
)

clean_data$Species <- droplevels(clean_data$Species)

Use clear object and column names, keep one kind of information in each column, and write every cleaning step in your script.

4. Summarise the data

Install dplyr once with install.packages("dplyr"), then load it in each new R session.

library(dplyr)

species_summary <- clean_data |>
  group_by(Species) |>
  summarise(
    samples = n(),
    mean_sepal_length = mean(Sepal.Length),
    sd_sepal_length = sd(Sepal.Length)
  )

species_summary

Save derived results separately from the raw data:

write.csv(
  species_summary,
  "results/species_summary.csv",
  row.names = FALSE
)

5. Create a figure

Install ggplot2 once with install.packages("ggplot2"), then create a simple plot showing the distribution of observations in each group.

library(ggplot2)

sepal_plot <- ggplot(
  clean_data,
  aes(x = Species, y = Sepal.Length, colour = Species)
) +
  geom_jitter(width = 0.12, alpha = 0.65) +
  geom_boxplot(width = 0.45, alpha = 0.15, outlier.shape = NA) +
  labs(
    x = "Species",
    y = "Sepal length (cm)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

sepal_plot

ggsave(
  "results/sepal_length_by_species.png",
  sepal_plot,
  width = 7,
  height = 5,
  dpi = 300
)

A useful figure should have readable labels, appropriate units and a visual encoding that makes the comparison clear.

Further learning

For a more complete treatment of data organisation, reshaping, cleaning and publication-quality graphics, see the external MulQuaBio: Data Management and Visualization in R chapter.

Back to workshop materials