Hermann’s Tortoises

Author

Jo Hardin

Published

March 3, 2026

Code
library(tidyverse) # ggplot, lubridate, dplyr, stringr, readr...
library(praise)

The Data

Golem Grad Tortoise Data

The datasets this week come from the paper “Sex Ratio Bias Triggers Demographic Suicide in a Dense Tortoise Population”. This topic seemed so interesting that even media like the New York Times picked it up: “Constant Sexual Aggression Drives Female Tortoises to Walk Off Cliffs”.

In an exceptionally dense island population of Hermann’s tortoises in Lake Prespa in North Macedonia, sexually coercive males dramatically overnumber females, inflict severe copulatory injuries and put them at risk of fatal falls from the island plateau’s sheer rock faces. Harassed females are emaciated, reproduce less frequently, produce smaller clutches and have lower annual survival rates compared to females from a neighbouring mainland population. Sixteen years of capture-recapture data reveal an ongoing extinction event and predict that the last island female will die in 2083.

  • Do recaptures happen more often in spring or summer?
  • Does it seem easier to recapture male or female tortoises?
  • What are the differences among tortoises from the mainland vs the ones from the island in terms of body mass or carapace length?

Thank you to Novica Nakov, Free Software Macedonia for curating this week’s dataset.

Code
clutch_size <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2026/2026-03-03/clutch_size_cleaned.csv')
tortoise <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2026/2026-03-03/tortoise_body_condition_cleaned.csv')
Code
clutch_size |> 
  ggplot() +
  geom_point(aes(x = body_mass_grams, y = eggs, color = age)) + 
  facet_wrap((~locality))

Code
tortoise |> 
  group_by(individual) |> 
  summarize(count = n()) |> 
  arrange(desc(count))
# A tibble: 2,139 × 2
   individual count
   <chr>      <int>
 1 644           27
 2 138           20
 3 465           20
 4 877           20
 5 446           19
 6 800           19
 7 335           18
 8 462           18
 9 893           18
10 898           18
# ℹ 2,129 more rows
Code
tortoise |> 
  filter(individual == 644) |> 
  ggplot() + 
  geom_point(aes(x = year, y = straight_carapace_length_mm)) 

Code
tortoise |> 
  group_by(individual) |> 
  summarize(count = n(), locality = first(locality), sex = first(sex))
# A tibble: 2,139 × 4
   individual count locality sex  
   <chr>      <int> <chr>    <chr>
 1 1             12 Plateau  m    
 2 10             4 Beach    f    
 3 100            4 Plateau  m    
 4 1000           1 Plateau  m    
 5 1001           7 Plateau  m    
 6 1003           2 Plateau  m    
 7 1004           1 Plateau  m    
 8 1005          12 Plateau  m    
 9 1006           4 Plateau  m    
10 1007           8 Plateau  m    
# ℹ 2,129 more rows
Code
tortoise |> 
  group_by(year, locality) |> 
  mutate(sex_ratio = mean(sex == "f")) |> 
  ggplot() + 
  geom_point(aes(x = sex_ratio, y = body_mass_grams, color = sex), 
             alpha = 0.5, size = 0.5) + 
  facet_wrap(~locality, scales = "free_x")

Code
tortoise |> 
  ggplot() + 
  geom_point(aes(x = body_mass_grams, y = body_condition_index, color = sex))

Code
tortoise |> 
  mutate(new_condition = body_mass_grams / straight_carapace_length_mm) |> 
  select(body_mass_grams, straight_carapace_length_mm, body_condition_index, new_condition)
# A tibble: 10,174 × 4
   body_mass_grams straight_carapace_length…¹ body_condition_index new_condition
             <dbl>                      <dbl>                <dbl>         <dbl>
 1            1230                       183.                 6.72          6.72
 2            1271                       184.                 6.90          6.90
 3            1239                       186.                 6.67          6.67
 4            1205                       187.                 6.46          6.46
 5            1300                       182.                 7.13          7.13
 6            1269                       186.                 6.84          6.84
 7            1302                       185                  7.04          7.04
 8            1230                       181                  6.80          6.80
 9            1305                       184                  7.09          7.09
10            1245                       184                  6.77          6.77
# ℹ 10,164 more rows
# ℹ abbreviated name: ¹​straight_carapace_length_mm

We expect the body condition of females to be higher. Turns out that the female tortoises are only perceptibly larger in the mainland, Konjsko.

Code
library(ggpattern) 

tortoise |> 
  mutate(locality = forcats::fct_relevel(locality, c("Konjsko", "Beach", "Plateau")),
         sex = ifelse(sex == "f", "F", "M")) |> 
  group_by(sex, locality) |> 
  mutate(ave_condition = mean(body_condition_index)) |> 
  ggplot() + 
  geom_violin_pattern(aes(y = body_condition_index, x = sex,
                  fill = locality, pattern = sex)) +
  geom_boxplot(aes(y = body_condition_index, x = sex),
               whisker.linewidth = 0, median.linewidth = 0,
               width = .2, outliers = FALSE)  +
  geom_point(aes(y = ave_condition, x = sex), 
             shape = "+", size = 5) +
  scale_pattern_manual(values = c("stripe", "none")) + 
  scale_fill_manual(values = c("#2F4F2F", "#6B8E23", "#A3B86C")) + 
  labs(pattern = "Sex", fill = "Locality", x = "", y = "Body condition") + 
  guides(fill = guide_legend(override.aes = list(pattern = "none")))  + 
  facet_grid(~ locality, switch = "x") + 
  theme_minimal()

Violin plot of the body condition of tortoises broken down by sex and location. Only Konjsko on the mainland has the body condition of female tortoises to be substantially higher than male tortoises. On the beach and plateau, the body conditions across genders is quite similar.

Comparing the body condition of Hermann’s tortoises at / near Golem Grad, an island near Macedonian. We expect female tortoises to have a higher body condition, but that is seen only on Konjsko mainland.
Code
praise()
[1] "You are transcendent!"