solutions session 1

Exercises 2

  1. Run ggplot(data = mtcars). What do you see and why?
  • an empty plot
  • ggplot creates the “canvas” of the plot with the right dimensions. But since we added no aestetics or layers, the canvas remains empty
  • if we wanted to create a plot from the mtcars data.frame, we could add aestethical mappings and a “geom”, which creates shapes to display the mapped data
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.1     ✔ readr     2.2.0
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.3     ✔ tibble    3.3.1
✔ lubridate 1.9.5     ✔ tidyr     1.3.2
✔ purrr     1.2.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
ggplot(
  data = mtcars,
  # map cyl to the x axis and mpg to the y axis
  mapping = aes(x = cyl, y = mpg)
) +
  geom_point() # add point geom to draw points

  1. In the function pb_collect() from paperboy, what do the arguments ignore_fails and connections do?
  • to check this, use the command ?paperboy::pb_collect() or ??pb_collect() and look for the function in the right package
  • ignore_fails ignores individual connections failing and moves on to the next URL to download data from
  • connections sets the number of connections opened at once
  1. Write a function that takes a numeric vector of miles per gallon consumption data and converts it to kilometer per liter. If anything other than a numeric vector is entered, the function should display an error (hint: see ?stop).
# reusing the formula from the section 'The pipe"
mpg_converter <- function(mpg) {
  if (!is.numeric(mpg)) {
    stop("only numeric vectors allowed")
  }
  kpl <- mpg * 0.4251
  return(kpl)
}
mpg_converter(c(20, 25, 30))
[1]  8.5020 10.6275 12.7530
mpg_converter(c("twenty-five"))
Error in `mpg_converter()`:
! only numeric vectors allowed
  1. In the code below, check the sizes of the intermediate objects with object.size().
file_link <- "https://raw.githubusercontent.com/shawn-y-sun/Customer_Analytics_Retail/main/purchase%20data.csv"
df <- read.csv(file_link)
filtered_df <- df[df$Age >= 50, ]
aggregated_df <- aggregate(
  filtered_df$Quantity,
  by = list(filtered_df$Day),
  FUN = sum
)
names(aggregated_df) <- c("day", "total_quantity")
aggregated_df[order(aggregated_df$total_quantity, decreasing = TRUE)[1:5], ]
    day total_quantity
162 162             73
460 460             73
123 123             61
183 183             60
340 340             57
object.size(df)
6812072 bytes
object.size(filtered_df)
1360320 bytes
object.size(aggregated_df)
6696 bytes
  1. How could the code above be improved if you only want the final result, the code should be readable and you care about memory usage?

It could be improved by not saving intermediate objects, but using the pipe instead. I also convert it to tidyverse code, but that is optional:

library(tidyverse)
final_df <- file_link |>
  read.csv() |>
  filter(Age >= 50) |>
  group_by(Day) |>
  summarise(total_quantity = sum(Quantity)) |>
  arrange(-total_quantity)
object.size(final_df)
6832 bytes
head(final_df)
# A tibble: 6 × 2
    Day total_quantity
  <int>          <int>
1   162             73
2   460             73
3   123             61
4   183             60
5   340             57
6   636             56

Another alterantive would be to wrap this in a function, as intermediate objects inside the function environment are destroyed and only the final object (which should be wrapped in return()) is added to the main environment/memory.

top_quantity_days <- function(file_link) {
  df <- read.csv(file_link)
  filtered_df <- df[df$Age >= 50, ]
  aggregated_df <- aggregate(
    filtered_df$Quantity,
    by = list(filtered_df$Day),
    FUN = sum
  )
  names(aggregated_df) <- c("day", "total_quantity")
  aggregated_df[order(aggregated_df$total_quantity, decreasing = TRUE)[1:5], ]
}
top_quantity_days(
  "https://raw.githubusercontent.com/shawn-y-sun/Customer_Analytics_Retail/main/purchase%20data.csv"
)
    day total_quantity
162 162             73
460 460             73
123 123             61
183 183             60
340 340             57

Exercises 4

  1. Use the function report_template() from my package jbgtemplates to start a new report
  • navigate to the repository of jbgtemplates: https://github.com/JBGruber/jbgtemplates
  • there you find that you can install the package with remotes::install_github("JBGruber/jbgtemplates")
  1. Add some simple analysis in it and render
  2. Play around with the formats and produce at least a PDF and Word output of your document
  • use format: pdf in the header of the document to render to a pdf
  • use format: docx in the header of the document to render to a Word file
  1. Think about how the structure of the document enhances reproducibility
  • putting the packages at the beginning of the document means that it will fail immediatly when one of the packages is not installed on someone else’s system, so it makes it easier to correct that and run the document
  • running sessionInfo() at the end of the document writes all the used packages and package versions to the output. This makes it possible to reconstruct the exact environment later if neccesary
  • writing in Quarto and switching between code and the explanation what the code is doing and why (i.e., literate programming) makes sure what you are doing is understandable to others (and your future self)