Monday Discussion Problems

Questions 1 (S3 Vehicle System)

part(1)

# Constructor for base class "vehicle"
vehicle <- function(make, model, year, mpg) {
  # --- validation ---
  if (!is.character(make)  || length(make)  != 1L)
    stop("`make` must be a single character string")
  if (!is.character(model) || length(model) != 1L)
    stop("`model` must be a single character string")
  if (!is.numeric(year)    || length(year)  != 1L)
    stop("`year` must be a single number")
  if (!is.numeric(mpg)     || length(mpg)   != 1L)
    stop("`mpg` must be a single number")

  # --- build object ---
  structure(
    list(
      make  = make,
      model = model,
      year  = year,
      mpg   = mpg
    ),
    class = "vehicle"
  )
}

part(2)

print.vehicle <- function(x, ...) {
  cat(sprintf("%s %s (%d)\n", x$make, x$model, x$year))
  cat(sprintf("  Fuel economy: %g.mpg\n", x$mpg))
  invisible(x)                 # preserve default console behaviour
}

part(3)

electric_car <- function(make, model, year, mpg = 0, battery_range) {
  if (!is.numeric(battery_range) || length(battery_range) != 1L || battery_range <= 0)
    stop("battery_range must be a positive number")

  obj <- vehicle(make, model, year, mpg)   # reuse the base constructor
  obj$battery_range <- battery_range
  class(obj) <- c("electric_car", "vehicle")
  obj
}

part (4)

print.electric_car <- function(x, ...) {
  NextMethod()                                 # prints the vehicle part
  cat(sprintf("  Battery range: %g.miles\n", x$battery_range))
  invisible(x)
}

Questions 2 (S4 Class)

part 5

## ---- S4 class definition
setClass(
  "Truck",
  slots = list(
    make = "character",
    model = "character",
    cargo_capacity = "numeric"  # tons
  ),
  validity = function(object) {
    if (!is.character(object@make) || length(object@make) != 1L)
      "Slot 'make' must be a single character string"
    else if (!is.character(object@model) || length(object@model) != 1L)
      "Slot 'model' must be a single character string"
    else if (!is.numeric(object@cargo_capacity) ||
             length(object@cargo_capacity) != 1L ||
             object@cargo_capacity <= 0)
      "Slot 'cargo_capacity' must be a single positive number (tons)"
    else
      TRUE
  }
)

part (6)

setMethod(
  "show",
  "Truck",
  function(object) {
    cat(sprintf(
      "%s %s\n  Cargo capacity: %g tons\n",
      object@make,
      object@model,
      object@cargo_capacity
    ))
  }
)

Questions 3 (Testing)

# ── Test S3 vehicles ────────────────────────────────────────────────────────
car1 <- vehicle("Toyota", "Camry", 2022, 32)
car2 <- vehicle("Honda",  "Civic", 2023, 36)

# ── Test electric car ───────────────────────────────────────────────────────
tesla <- electric_car("Tesla", "Model 3", 2024, 0, 300)

# ── Test S4 truck ───────────────────────────────────────────────────────────
library(methods)  
truck1 <- new("Truck", make = "Ford", model = "F‑150", cargo_capacity = 2.5)

# ── Print / show the objects ────────────────────────────────────────────────
print(car1)
## Toyota Camry (2022)
##   Fuel economy: 32.mpg
print(car2)
## Honda Civic (2023)
##   Fuel economy: 36.mpg
print(tesla)
## Tesla Model 3 (2024)
##   Fuel economy: 0.mpg
##   Battery range: 300.miles
show(truck1)
## Ford F‑150
##   Cargo capacity: 2.5 tons

Wednesday Discussion Problems

# --------------------------------------------------------------------------
# 1. Bar plot – mean carat by cut & colour
# --------------------------------------------------------------------------
bar_plot <- diamonds %>% 
  group_by(cut, color) %>%                       
  summarise(mean_carat = mean(carat), .groups = "drop") %>% 
  ggplot(aes(x = cut, y = mean_carat, fill = color)) +
  geom_col(position = position_dodge()) +
  labs(
    title = "Average Carat by Cut and Color",
    x     = "Cut",
    y     = "Average Carat",
    fill  = "Colour"
  ) +
  scale_fill_viridis_d(option = "viridis") +
  theme_bw()

# --------------------------------------------------------------------------
# 2. Scatter plot – carat vs price, 30 diamonds per cut
# --------------------------------------------------------------------------
set.seed(82294)  # reproducible sampling
diamonds_sample <- diamonds %>% 
  group_by(cut) %>% 
  sample_n(30) %>% 
  ungroup()

scatter_plot <- ggplot(
  diamonds_sample,
  aes(x = carat, y = price, colour = cut, shape = cut)
) +
  geom_point(size = 5) +
  labs(
    title  = "Scatter Plot of Carat vs Price by Cut",
    x      = "Carat",
    y      = "Price",
    colour = "Cut",
    shape  = "Cut"
  ) +
  scale_color_viridis_d(option = "viridis") +
  scale_shape_manual(
    values = c(
      "Fair"      = 16,  # filled circle ●
      "Good"      = 17,  # filled triangle ▲
      "Very Good" = 15,  # filled square ■
      "Premium"   = 3,   # plus +
      "Ideal"     = 7    # square with X inside ⌧
    )
  ) +
  theme_bw()

# --------------------------------------------------------------------------
# Display
# --------------------------------------------------------------------------
bar_plot

scatter_plot