Visualising dog morphology

In this activity we’ll revisit the dog morphology data set, and create some plots using ggplot()

We begin by loading some packages

library("readxl")
library("dplyr")
library("stringr")
library("janitor")
library("tidyr")
library("ggplot2")

(Note we do not show the messages that get printed when the packages are loaded.)

Dog morphology

In the third part of the activity, we will briefly look at a data set of information on the morphology of dog breeds. Again, the data are somewhat messy and need a little cleaning before we can begin working with them.

The data are in two separate sheets within the the dog-morphology.xlsx Excel workbook. First we have skull length and width measurements on several males and females from a number of dog breeds.

We load the data from the CephalicIndex sheet, clean the variable names, and then change the sex variable to have nice labels. Copy and paste this code into your script, but make sure you understand what each line is doing before you run the code:

dog_skull <-  read_xlsx("data/dog-morphology/dog-morphology.xlsx",
  sheet = "CephalicIndex") |>
  janitor::clean_names() |>
  mutate(
    sex = case_when(
      sex == "M" ~ "male",
      sex == "F" ~ "female"
    )
  )

The second sheet contains average weight and height data for each breed, plus the typical height and weight ranges for male and female dogs of each breed. This data set is messy because it doesn’t have a label for each column in the sheet. Again, copy and paste the code into your script and study it for a few minutes before you run it. When you do run the code below you will see

New names:
• `` -> `...4`
• `` -> `...6`
• `` -> `...9`
• `` -> `...11`

printed in the console: This is fine! When we run janitor::clean_names() on the data these weird names ...4 etc are turned into x4 etc., which is why we use the rename() function to give names to these unlabeled columns as well as fix the labels for those that are named:

dog_hw <- read_xlsx("data/dog-morphology/dog-morphology.xlsx",
  sheet = "HeightWeight") |>
  janitor::clean_names() |>
  rename(
    weight_lower_male = weight_range_male_lowest_and_highest,
    weight_upper_male = x4,
    weight_lower_female = weight_range_female,
    weight_upper_female = x6,
    height_lower_male = height_range_male,
    height_upper_male = x9,
    height_lower_female = height_range_female,
    height_upper_female = x11,
  )
New names:
• `` -> `...4`
• `` -> `...6`
• `` -> `...9`
• `` -> `...11`

We need to the average height and weight for male and female dogs of each breed to the dog_hw data frame, and create sex and height and weight columns:

dog_hw <- dog_hw |>
  mutate(
    male_weight = (weight_lower_male + weight_upper_male) / 2,
    male_height = (height_lower_male + height_upper_male) / 2,
    female_weight = (weight_lower_female + weight_upper_female) / 2,
    female_height = (height_lower_female + height_upper_female) / 2
  )  |>
  select(breed, starts_with("male"), starts_with("female")) |>
  pivot_longer(
    !breed,
    names_to = c("sex", "variable"),
    names_sep = "_",
    values_to = "value"
  ) |>
  pivot_wider(
    id_cols = c(breed, sex),
    names_from = "variable",
    values_from = "value"
  )
NoteQuestion

Produce a scatter plot of skull_length on the x axis and skull_width() on the y axis

Solution

dog_skull |>
  ggplot(aes(x = skull_length, y = skull_width)) +
  geom_point()

NoteQuestion

How would you modify the previous plot to show the sex variable using colour?

Solution

dog_skull |>
  ggplot(aes(x = skull_length, y = skull_width, colour = sex)) +
  geom_point()

NoteQuestion

How would you modify the original plot to use different shapes for sex and colour the points blue?

Solution

dog_skull |>
  ggplot(aes(x = skull_length, y = skull_width, shape = sex)) +
  geom_point(colour = "blue")
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

NoteQuestion

Take a look at the dog_skull data and choose five (5) breeds you are familiar with (or like the look of).

Filter the data to retain just your chosen five breeds and plot the length and width of each skull for this subset. Use colour to differentiate between breeds.

Solution

I’m not very familiar with dog breeds, so I chose my breeds randomly

set.seed(42)
breeds_want <- dog_skull |>
  distinct(breed) |>
  slice_sample(n = 5) |>
  pull(breed)

Then I filter the data

dog_skull |>
  filter(breed %in% breeds_want) |>
  ggplot(aes(x = skull_length, y = skull_width, colour = breed)) +
  geom_point()

NoteQuestion

Using dog_hw, create a scatter plot of height on the x axis and weight on the y axis.

Solution

dog_hw |>
  ggplot(aes(x = height, y = weight)) +
  geom_point()

NoteQuestion

Modify the previous plot to include:

  • colour by sex
  • fill by sex
  • add linear regression lines per sex

Solution

dog_hw |>
  ggplot(aes(x = height, y = weight, colour = sex, fill = sex)) +
  geom_point() +
  geom_smooth(method = "lm")
`geom_smooth()` using formula = 'y ~ x'