6B: Using Data Manipulation to Understand Mammalian Sleep
From Freepik
The msleep data set is an updated and expanded version of the mammals sleep data set. It is available in ggplot2. Updated sleep times and weights were taken from V. M. Savage and G. B. West. A quantitative, theoretical framework for understanding mammalian sleep. Proceedings of the National Academy of Sciences, 104 (3):1051-1056, 2007.
The data set has 83 observations and 11 variables:
name - common name
genus - taxonomic rank in biological classification
vore - carnivore, omnivore or herbivore?
order - specific levels in biological taxonomy
conservation - the conservation status of the animal
sleep_total - total amount of sleep, in hours
sleep_rem - rem sleep, in hours
sleep_cycle - length of sleep cycle, in hours
awake - amount of time spent awake, in hours
brainwt - brain weight in kilograms
bodywt - body weight in kilograms
Broad types of diets in animals are:
From Science Notes
Conservation statuses include:
From Reclaimed Earth
In this lesson, we will use dplyr for data manipulation to better under mammalian sleep. Recall that dplyr implements the following verbs from the grammar of data manipulation**:
slice() to subset rows using their positions
filter() to keep rows that match a condition
select() to keep or drop columns
mutate() to modify existing variables or add new variables
arrange() to reorder rows using column names
summarize() to reduce variables to values
group_by() to perform grouped (aggregated) operations
The pipe operators%>% from the magrittr (muh-GREET-er) package or |> from base R are useful for step-by-step computations in a forward manner.
# A tibble: 22 × 11
name genus vore order conservation sleep_total sleep_rem sleep_cycle awake
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Cheet… Acin… carni Carn… lc 12.1 NA NA 11.9
2 Mount… Aplo… herbi Rode… nt 14.4 2.4 NA 9.6
3 Three… Brad… herbi Pilo… <NA> 14.4 2.2 0.767 9.6
4 Chinc… Chin… herbi Rode… domesticated 12.5 1.5 0.117 11.5
5 Long-… Dasy… carni Cing… lc 17.4 3.1 0.383 6.6
6 Weste… Euta… herbi Rode… <NA> 14.9 NA NA 9.1
7 Domes… Felis carni Carn… domesticated 12.5 3.2 0.417 11.5
8 Thick… Lutr… carni Dide… lc 19.4 6.6 NA 4.6
9 Mongo… Meri… herbi Rode… lc 14.2 1.9 NA 9.8
10 Golde… Meso… herbi Rode… en 14.3 3.1 0.2 9.7
# ℹ 12 more rows
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>
💻 Hands-On
Subset msleep to only carnivores who weigh more than 50 kg.
Answer
msleep |>filter(vore =='carni', bodywt >50)
# A tibble: 8 × 11
name genus vore order conservation sleep_total sleep_rem sleep_cycle awake
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Pilot … Glob… carni Ceta… cd 2.7 0.1 NA 21.4
2 Gray s… Hali… carni Carn… lc 6.2 1.5 NA 17.8
3 Tiger Pant… carni Carn… en 15.8 NA NA 8.2
4 Jaguar Pant… carni Carn… nt 10.4 NA NA 13.6
5 Lion Pant… carni Carn… vu 13.5 NA NA 10.5
6 Caspia… Phoca carni Carn… vu 3.5 0.4 NA 20.5
7 Common… Phoc… carni Ceta… vu 5.6 NA NA 18.4
8 Bottle… Turs… carni Ceta… <NA> 5.2 NA NA 18.8
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>
💻 Hands-On
Subset msleep to keep only the columns name, awake, sleep_total, sleep_rem, and sleep_cycle.
What does the following code do? Modify the code to obtain the sample means of brainwt and sleep_cycle?
msleep |>drop_na(brainwt, sleep_cycle)
Answer
drop_na() removes rows (observations) containing missing values (NAs). If we put variable(s) in, it will remove only rows having missing values for those particular variable(s). Thus, after putting brainwt and sleep_cycle in drop_na(), we can find the sample means of these variables.
# A tibble: 83 × 11
name genus food_preference order conservation_status sleep_total sleep_rem
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl>
1 Cheetah Acin… carni Carn… lc 12.1 NA
2 Owl mo… Aotus omni Prim… <NA> 17 1.8
3 Mounta… Aplo… herbi Rode… nt 14.4 2.4
4 Greate… Blar… omni Sori… lc 14.9 2.3
5 Cow Bos herbi Arti… domesticated 4 0.7
6 Three-… Brad… herbi Pilo… <NA> 14.4 2.2
7 Northe… Call… carni Carn… vu 8.7 1.4
8 Vesper… Calo… <NA> Rode… <NA> 7 NA
9 Dog Canis carni Carn… domesticated 10.1 2.9
10 Roe de… Capr… herbi Arti… lc 3 NA
# ℹ 73 more rows
# ℹ 4 more variables: sleep_cycle <dbl>, awake <dbl>, brainwt <dbl>,
# bodywt <dbl>
💻 Hands-On
What does the following code do? Can you think of a different way to obtain the same result?
msleep |>arrange(desc(sleep_cycle)) |>slice(1:5)
Answer
The code sorts the data in decreasing lengths of sleep cycle and then keeps the first five rows. This can be done with less code using slice_max()
msleep |>slice_max(sleep_cycle, n =5)
# A tibble: 5 × 11
name genus vore order conservation sleep_total sleep_rem sleep_cycle awake
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Human Homo omni Prim… <NA> 8 1.9 1.5 16
2 Chimpa… Pan omni Prim… <NA> 9.7 1.4 1.42 14.3
3 Horse Equus herbi Peri… domesticated 2.9 0.6 1 21.1
4 Brazil… Tapi… herbi Peri… vu 4.4 1 0.9 19.6
5 Three-… Brad… herbi Pilo… <NA> 14.4 2.2 0.767 9.6
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>
💻 Hands-On
Subset msleep to 3 carnivores with the smallest weights.
Answer
msleep |>filter(vore =='carni') |>slice_min(bodywt, n =3)
# A tibble: 3 × 11
name genus vore order conservation sleep_total sleep_rem sleep_cycle awake
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Northe… Onyc… carni Rode… lc 14.5 NA NA 9.5
2 Thick-… Lutr… carni Dide… lc 19.4 6.6 NA 4.6
3 Slow l… Nyct… carni Prim… <NA> 11 NA NA 13
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>
Second Part
💻 Hands-On
What does the following code do? Modify the code so that missing values are removed.
msleep |>select(vore) |>distinct()
Answer
The code keeps the vore column only and returns only unique (distinct) categories of this column. However, missing values NA are also considered a category. To avoid that, we should drop the missing values.
msleep |>select(vore) |>distinct() |>drop_na()
# A tibble: 4 × 1
vore
<chr>
1 carni
2 omni
3 herbi
4 insecti
💻 Hands-On
Subset msleep to distinct rows of vore and conservation that have no missing values.
# A tibble: 16 × 2
vore conservation
<chr> <chr>
1 carni lc
2 herbi nt
3 omni lc
4 herbi domesticated
5 carni vu
6 carni domesticated
7 herbi lc
8 herbi en
9 insecti lc
10 herbi cd
11 carni cd
12 herbi vu
13 carni en
14 carni nt
15 insecti en
16 omni domesticated
💻 Hands-On
Subset msleep to only herbivores and then order the data by name.
Answer
msleep |>filter(vore =='herbi') |>arrange(name)
# A tibble: 32 × 11
name genus vore order conservation sleep_total sleep_rem sleep_cycle awake
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Afric… Loxo… herbi Prob… vu 3.3 NA NA 20.7
2 Arcti… Sper… herbi Rode… lc 16.6 NA NA 7.4
3 Asian… Elep… herbi Prob… en 3.9 NA NA 20.1
4 Brazi… Tapi… herbi Peri… vu 4.4 1 0.9 19.6
5 Chinc… Chin… herbi Rode… domesticated 12.5 1.5 0.117 11.5
6 Cotto… Sigm… herbi Rode… <NA> 11.3 1.1 0.15 12.7
7 Cow Bos herbi Arti… domesticated 4 0.7 0.667 20
8 Degu Octo… herbi Rode… lc 7.7 0.9 NA 16.3
9 Donkey Equus herbi Peri… domesticated 3.1 0.4 NA 20.9
10 Easte… Tami… herbi Rode… <NA> 15.8 NA NA 8.2
# ℹ 22 more rows
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>
💻 Hands-On
Subset msleep to only species whose conservation status is least concern. Then, remove column conservation and all rows with missing values.
Subset msleep to all the mammals who are generally more awake than asleep.
Answer
msleep |>filter(awake > sleep_total)
# A tibble: 52 × 11
name genus vore order conservation sleep_total sleep_rem sleep_cycle awake
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Cow Bos herbi Arti… domesticated 4 0.7 0.667 20
2 North… Call… carni Carn… vu 8.7 1.4 0.383 15.3
3 Vespe… Calo… <NA> Rode… <NA> 7 NA NA 17
4 Dog Canis carni Carn… domesticated 10.1 2.9 0.333 13.9
5 Roe d… Capr… herbi Arti… lc 3 NA NA 21
6 Goat Capri herbi Arti… lc 5.3 0.6 NA 18.7
7 Guine… Cavis herbi Rode… domesticated 9.4 0.8 0.217 14.6
8 Grivet Cerc… omni Prim… lc 10 0.7 NA 14
9 Star-… Cond… omni Sori… lc 10.3 2.2 NA 13.7
10 Afric… Cric… omni Rode… <NA> 8.3 2 NA 15.7
# ℹ 42 more rows
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>
💻 Hands-On
Subset msleep to contain only carnivores with body weights greater than 50 kg. Then, arrange the data in ascending order of body weight. Finally, keep only columns name, bodywt, and brainwt in that order.
# A tibble: 8 × 3
name bodywt brainwt
<chr> <dbl> <dbl>
1 Common porpoise 53.2 NA
2 Gray seal 85 0.325
3 Caspian seal 86 NA
4 Jaguar 100 0.157
5 Lion 161. NA
6 Tiger 163. NA
7 Bottle-nosed dolphin 173. NA
8 Pilot whale 800 NA
💻 Hands-On
We want to subset msleep to all mammals whose brain weight is less than 2. However, the following code has an error. Fix the error in the code.
We want to subset msleep to show just the REM sleep amounts for carnivores, where data is arranged in order of genus. However, the following code has an error. Fix the error in the code.
The given code has an error, because genus was not selected when subsetting columns. It is better to arrange by genus before filtering rows or selecting columns.
In the given code, summarize() gives a single number showing the sample mean of the amount of time spent awake, while mutate() gives a whole column with a single value (sample mean of awake). To put it in another way, summarize() gives us summary statistics, while mutate() changes the column awake and returns the new data set
💻 Hands-On
Determine the average amount of time spent in REM sleep based on non-missing values.
Answer
Consider the following ways:
# method 1: drop NAs then calculate the sample meanmsleep |>select(sleep_rem) |>drop_na() |>summarize(mean_sleep_rem =mean(sleep_rem))
# A tibble: 1 × 1
mean_sleep_rem
<dbl>
1 1.88
# method 2: use the na.rm = TRUE option of mean()msleep |>summarize(mean_sleep_rem =mean(sleep_rem, na.rm =TRUE))
# A tibble: 1 × 1
mean_sleep_rem
<dbl>
1 1.88
💻 Hands-On
Calculate the median body weight and the maximum brain weight of each vore group.