← Back to Biology Hub
Learn RMade by Dr Daniel Mompel Riera · NLCS Jeju

Beyond the curriculum

Learn R, the programming language scientists use to analyse data.

R is free. You type short instructions, and R turns your numbers into graphs and statistical tests. You learn it by doing, right here: the first time, this page downloads R (about 20 seconds), but nothing is installed on your computer. For your own projects, such as an IA, the IB courses end by showing you how to install R and RStudio.

Where do you start?

Never used R? Start here Year 8 · also for IGCSE Variation in our class Measure your class: height, arm span, hand span, shoe size. Then summarise, graph and compare two groups, one small step at a time. 11 stages · your class data, or a sample class Start → IB Biology · Tool 3 Statistics in R Averages, box plots, SD and SE, the p-value, then the three tests the IB asks for: χ², the t-test and correlation. Every idea told step by step. 12 stages · from raw data to RStudio Start → IB Biology · B1.1 practical Starch curves in R Turn your colorimeter readings into a calibration curve: average the repeats, choose the straight part, fit the line, and read what R² tells you. Runs here · or download it for RStudio Start →

Why learn R?

Two things R does that a spreadsheet cannot

Before any explanation: drag the first picture, and look at how the second is made.

drag to rotate · arrow keys work too
healthy early disease late disease

Every dot is one patient, placed by about twenty thousand gene measurements squashed down to three numbers. Drag it. The two disease groups start sitting on top of one another and come apart as you turn the cloud — which is exactly why this one has to be three-dimensional, and why it has to move.

3D earns its place here because you are hunting for clusters in a cloud. On a bar chart or a pie chart it only distorts what you are trying to read, and Excel will happily let you make one. The calculation is a single line, prcomp(genes); drawing it takes about ten more. This one is drawn for the page in JavaScript, not by R — JavaScript is the only language a browser runs, and R makes the same kind of interactive figure from one command.

Annual GDP growth, four economies, 2005–2024one map and four charts, drawn together as a single figureUnited StatesIndiaBrazilChinaEvery country the data covers is on the map; the four in colour are the four charted.United States-2.6-5051015India-5.8Brazil-3.5-505101520052024China2.220052024GDP growth / % per yearyear — shaded band marks 2020

One R script made all of this — the map, the four charts, and the layout that joins them into one picture. The colours are written down once and handed to both halves, so a country is the same colour wherever it turns up.

Excel can colour a map. What it cannot do is tie that map's colours to four separate charts, or combine the five into a single figure — that part is done by hand, again, every time the numbers change.

Show me the 53 lines
# Runs as-is: it fetches the map itself, numbers are below.
# tidyverse = data handling + ggplot2, sf = map shapes,
# patchwork = sticks finished plots together.
for (pkg in c("tidyverse", "sf", "patchwork"))
  if (!requireNamespace(pkg, quietly = TRUE))
    install.packages(pkg)

library(tidyverse); library(sf); library(patchwork)

# one palette, handed to BOTH halves of the figure
pal <- c("United States" = "#3A46A8", "India" = "#B4741A",
         "Brazil"        = "#0E7A66", "China" = "#A8326B")

growth <- tibble(
  year    = rep(2005:2024, times = 4),
  country = rep(names(pal), each = 20),
  gdp_growth = c(
    # United States
    3.5, 2.8, 2.0, 0.1,-2.6, 2.7, 1.6, 2.3, 2.1, 2.5,
    2.9, 1.8, 2.5, 3.0, 2.5,-2.2, 6.1, 2.5, 2.9, 2.8,
    # India
    9.3, 9.3, 9.8, 3.9, 8.5,10.3, 6.6, 5.5, 6.4, 7.4,
    8.0, 8.3, 6.8, 6.5, 3.9,-5.8, 9.1, 7.2, 8.2, 6.5,
    # Brazil
    3.2, 4.0, 6.1, 5.1,-0.1, 7.5, 4.0, 1.9, 3.0, 0.5,
   -3.5,-3.3, 1.3, 1.8, 1.2,-3.3, 5.0, 3.0, 2.9, 3.4,
    # China
   11.4,12.7,14.2, 9.7, 9.4,10.6, 9.6, 7.9, 7.8, 7.4,
    7.0, 6.8, 6.9, 6.7, 6.0, 2.2, 8.4, 3.0, 5.2, 5.0))

url <- paste0("https://raw.githubusercontent.com/",
              "nvkelso/natural-earth-vector/master/",
              "geojson/ne_110m_admin_0_countries.geojson")
world <- read_sf(url)

# The map says "United States of America", our table says
# "United States". Making two sets of names agree is the
# commonest real data job there is. Here it is one line.
world$country <- recode(world$ADMIN,
  "United States of America" = "United States")

map <- ggplot(world) +
  geom_sf(aes(fill = country), colour = "grey85") +
  scale_fill_manual(values = pal, na.value = "grey88",
                    guide = "none") +
  coord_sf(crs = "+proj=robin") +
  theme_void()

lines <- ggplot(growth,
                aes(year, gdp_growth, colour = country)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_area(aes(fill = country), alpha = 0.15) +
  geom_line(linewidth = 0.8) +
  facet_wrap(~ country) +          # four panels, one line
  scale_colour_manual(values = pal, guide = "none") +
  scale_fill_manual(values = pal, guide = "none") +
  labs(x = "year", y = "GDP growth / % per year") +
  theme_minimal()

map + lines                        # patchwork joins them
ggsave("figure.png", width = 11, height = 4.5)

You are not expected to understand this yet. Notice only two things. The palette is written once and used by both plots, which is why the map and the lines can never drift out of agreement. And map + lines is the entire layout step — you add two pictures together the way you would add two numbers.

Roughly 53 lines of R — about half of them the twenty years of numbers. Expandable above; it runs as it stands. Map: real Natural Earth outlines, Robinson projection. The copy above is drawn into this page; the R in the expander is genuine and makes the same figure. The growth figures follow the real pattern but are illustrative.

Each of those is one script. Nothing was clicked, dragged or nudged into place by hand, and running the script again next year gives back the identical picture with the new numbers in it.

How R runs here