---
title: "Project 4: Errors, Date & Time, and Loop Speed"
author: "Boluwatife Ajibade"
date: "December 07, 2025"
format:
  word: default
  pdf: default
---

# πŸ“¦ Environment Setup

This chunk installs and loads the necessary packages, specifically `tidyverse` (which includes `dplyr` and `ggplot2`) and `lubridate`, which are essential for date/time manipulation and efficient coding practices.

```{r setup}'''
# Install packages if they are not already installed
if (!requireNamespace("tidyverse", quietly = TRUE)) {
  install.packages("tidyverse")
}
if (!requireNamespace("lubridate", quietly = TRUE)) {
  install.packages("lubridate")
}

# Load the necessary packages and suppress startup messages for cleaner output
suppressPackageStartupMessages(library(tidyverse))
suppressPackageStartupMessages(library(lubridate))

🐞 Part 1: Debugging and Profiling

This section addresses R’s profiling and debugging tools and solves common R code errors.

1. Profiling and Debugging Functions

The following functions are used in R for performance profiling (identifying bottlenecks) and debugging (finding the source of errors).

Function Purpose Explanation
(a) Turn on the profiler Rprof() Starts the R profiler, which records the amount of time spent on function calls.
(b) Calculate time spent in functions summaryRprof() Reads the output file from Rprof() and summarizes the execution time spent in each function.
(c) Show the sequence of calls traceback() Prints the call stack after an error occurs, showing the sequence of functions that led to the error.
(d) Debug an error in a function debug() Sets a flag on a specific function, causing execution to pause and enter the interactive debugger (browser()) when that function is called.
(e) Investigate the error environment recover() Used after an error occurs (often set globally via options(error = recover)). It allows the user to navigate the call stack (traceback) and investigate the environment of any function on the stack.

2. Solving Common R Code Problems

This section provides the fixes for the common R syntax and logical errors listed.

(2a) Problem: Incomplete String

Error Type: Syntax Error (<text>:3:0: unexpected end of input)

The original code snippet:

myString <- "Good things come in threes

Fix and Explanation: The string begins with a double quote but does not end with one before the line break. R requires strings to be properly enclosed on the same line (unless using a multiline string feature which wasn’t used here). The fix is to close the string.

```{r part1_2a_fix}’’’ # FIX: Close the string with a double quote on the same line. my_string <- β€œGood things come in threes”

Display the fixed object

my_string


### (2b) Problem: Misspelled Function

**Error Type:** Name Error (`could not find function "means"`)

The original code snippet:

```r
age <- c(28, 48, 47, 71, 22, 80, 48, 30, 31)
means(age)

Fix and Explanation: The user misspelled the built-in function mean(). R is case-sensitive and function names must be spelled correctly.

```{r part1_2b_fix}’’’ age <- c(28, 48, 47, 71, 22, 80, 48, 30, 31)

FIX: Use the correct function name: mean()

result_mean <- mean(age)

Display the result

result_mean


### (2c) Problem: Object Not Found

**Error Type:** Name Error (`object 'name_of_a_variable_that_doesnt_exist' not found`)

The original code snippet:

```r
name_of_a_variable_that_doesnt_exist + 1 * pi^2

Fix and Explanation: The error occurred because the variable was used before it was assigned a value. The fix is to first assign a value to the object.

```{r part1_2c_fix}’’’ # FIX: Assign a value to the variable before use. name_of_a_variable_that_doesnt_exist <- 5

Rerunning the calculation

result_calc <- name_of_a_variable_that_doesnt_exist + 1 * pi^2

Display the result

result_calc


### (2d) Problem: File Access/Path Error

**Error Type:** File/I/O Error (`zip file 'C:\Users\mans\Data\some_file.xlsx' cannot be opened`)

**Fix and Explanation:**
This error is often caused by one of three things:

1.  **File Not Found:** The file path is incorrect or the file was moved/deleted.
2.  **Permissions:** R does not have permission to read that directory.
3.  **Invalid Path Syntax:** In R (especially on Windows), backslashes (`\`) can be problematic because they are used as escape characters.

The fix is to replace the single backslashes with either double backslashes (`\\`) or forward slashes (`/`). A forward slash is universally safer in R for path specification.

**Example Fix (Conceptual, as file doesn't exist):**

```r
# Conceptual Fix: Replacing backslashes with forward slashes
# original_path <- "C:\Users\mans\Data\some_file.xlsx"
fixed_path <- "C:/Users/mans/Data/some_file.xlsx"

# The command that caused the error (e.g., read_excel) would be run with the fixed path.
# readxl::read_excel(fixed_path) 

(2e) Problem: Missing Operator

Error Type: Syntax/Operator Error (attempt to apply non-function)

The original code snippet:

1+2(2+3)

Fix and Explanation: In R, as in many programming languages, multiplication must be explicitly denoted with the multiplication operator (*). R interprets 2(2+3) as an attempt to call a function named 2 with the argument (2+3), which is not valid.

```{r part1_2e_fix}’’’ # FIX: Insert the multiplication operator () between 2 and (2+3). result_math <- 1 + 2 (2 + 3)

Display the result

result_math


-----

# πŸ“… Part 2: Date and Time Formatting and Operations

This section demonstrates various date and time format codes and performs date arithmetic.

## 3\. Date Format Examples

The `format()` function is used to convert a date or time object into a character string based on specified codes. The examples below use a base date object created from `2025-07-25 09:05:01`.

```{r part2_3_base_date}'''
# Create a base POSIXct date/time object for demonstration
base_datetime <- as.POSIXct("2025-07-25 09:05:01", tz = "America/Chicago")
Code Description Example R Code Example Output Explanation
(a) %a Abbreviated weekday name. format(base_datetime, "%a") Fri The abbreviated name of the day of the week (Friday).
(b) %c Locale-specific date and time. format(base_datetime, "%c") Fri Jul 25 09:05:01 2025 A full, standard date and time string for the current locale.
(c) %j Day of the year (001-366). format(base_datetime, "%j") 206 The 206th day of the year 2025.
(d) %m Month as a decimal number (01-12). format(base_datetime, "%m") 07 The month of July, represented as the number 07.
(e) %p AM/PM indicator. format(base_datetime, "%p") AM The morning indicator for a time before noon.
(f) %S Seconds as a decimal number (00-61). format(base_datetime, "%S") 01 The seconds component of the time (01 second).
(g) %x Locale-specific date representation. format(base_datetime, "%x") 07/25/25 A common short date format (MM/DD/YY) for the US locale.

4. Date and Time Arithmetic

This section uses the lubridate package for robust and accurate date and time calculations.

(4a) Subtract Date 2020-01-01 from 2021-01-01

The result should be the number of days between the two dates.

```{r part2_4a_subtract_date}’’’ # Define the dates date_end <- as.Date(β€œ2021-01-01”) date_start <- as.Date(β€œ2020-01-01”)

Subtract the dates (the result is a difftime object, measured in days)

date_difference <- date_end - date_start

Display the result

date_difference


**Output Explanation (4a):**
The output shows a **difftime** object of 366 days. This is correct because 2020 was a leap year, containing 366 days.

### (4b) Subtract Time "2022-11-08 03:14:35 PST" from "2022-11-09 26:14:35 PST"

The time "26:14:35" is not a standard format and must be corrected before calculation. "26 hours" is equivalent to 24 hours (1 day) plus 2 hours, meaning the time is actually 02:14:35 on the *next* day (2022-11-10). The `lubridate::ymd_hms()` function handles non-standard times gracefully by rolling them over.

```{r part2_4b_subtract_time}'''
# Define the times using lubridate::ymd_hms, which handles the "26" hour rollover
time_end <- ymd_hms("2022-11-09 26:14:35", tz = "PST") # This becomes 2022-11-10 02:14:35
time_start <- ymd_hms("2022-11-08 03:14:35", tz = "PST")

# Subtract the times (result is a difftime object)
time_difference <- time_end - time_start

# Display the result
time_difference

Output Explanation (4b): The difference is 47 hours (1 day and 23 hours). This results from time_end rolling over to November 10th (48 hours from start) and then correcting for the one hour difference in the hours component (02:xx:xx vs 03:xx:xx). Specifically, it’s 1 day and 23 hours: \((24 \text{ hours} \times 2 \text{ days}) - 1 \text{ hour} = 47 \text{ hours}\).

(4c) Extract Seconds of the Day and Day from Data

Assuming we have a date-time object, we can extract the seconds of the day and the day of the week.

```{r part2_4c_extract_seconds_day}’’’ # Create a sample POSIXct object sample_datetime <- as.POSIXct(β€œ2025-07-25 15:30:00”, tz = β€œUTC”)

Extract seconds of the day

(30 seconds + 30 minutes * 60 seconds/min + 15 hours * 3600 seconds/hr)

seconds_of_day <- hour(sample_datetime) * 3600 + minute(sample_datetime) * 60 + second(sample_datetime)

Extract day of the week (e.g., Friday)

day_of_week <- weekdays(sample_datetime)

Display results

cat(β€œSample Date/Time:”, as.character(sample_datetime), β€œβ€) cat(β€œSeconds of the Day:”, seconds_of_day, β€œβ€) cat(β€œDay of the Week:”, day_of_week, β€œβ€)


### (4d) Find Intervals Between the Dates

Intervals represent the exact span of time between two date-time points. We can use the difference from part (4a) to create an interval.

```{r part2_4d_interval}'''
# Define start and end points
date_start_i <- as_datetime("2023-05-15 10:00:00")
date_end_i <- as_datetime("2023-05-20 14:30:00")

# Create an interval object using lubridate::interval()
time_interval <- interval(date_start_i, date_end_i)

# Display the interval
time_interval

# Calculate the length of the interval in hours (as a demonstration)
length_in_hours <- time_interval / hours(1)

# Display the length
cat("Length of interval in hours:", length_in_hours)

(4e) Generate Monthly Sequence of Dates of Length 5

We can use seq.Date() in base R or add_with_rollback() with days(0) in lubridate for robustness.

```{r part2_4e_monthly_sequence}’’’ # Define the starting date start_date <- as.Date(β€œ2020-04-21”)

Generate a sequence of 5 dates, spaced by one month

seq.Date handles the monthly spacing

monthly_sequence <- seq.Date( from = start_date, by = β€œmonth”, length.out = 5 )

Display the sequence

monthly_sequence


-----

# πŸ’» Part 3: Loop and Apply Functions

This section demonstrates the use of R's `apply` family functions for efficient iteration.

## 5\. Demonstrating `apply` Functions

The `apply` functions are typically more compact and often faster than standard `for` loops, especially for simple operations on lists and vectors.

### (5a) `lapply()`: List Apply

**Purpose:** Applies a function over a **list** or **vector** and returns the result as a **list**.

```{r part2_5a_lapply}'''
# Create a list of three vectors
data_list <- list(
  set_a = c(10, 20, 30),
  set_b = c(5, 15, 25),
  set_c = c(100, 200, 300)
)

# Use lapply to calculate the mean of each vector in the list
# The result will be a list containing the three calculated means.
lapply_result <- lapply(
  X = data_list,
  FUN = mean
)

# Display the result
lapply_result

Explanation of Use (5a): lapply() iterated over the three elements (set_a, set_b, set_c) of data_list. For each element, it applied the mean() function. Since the output structure is always a list, the result is a list containing the calculated means (20, 15, and 200).

(5b) sapply(): Simplify Apply

Purpose: Applies a function over a list or vector and attempts to simplify the result to the lowest possible dimension, usually a vector or a matrix.

```{r part2_5b_sapply}’’’ # Use sapply on the same list as above # The output will be simplified from a list to a named numeric vector. sapply_result <- sapply( X = data_list, FUN = mean )

Display the result

sapply_result


**Explanation of Use (5b):**
`sapply()` performed the exact same operation as `lapply()`. However, because the results were all single numeric values, `sapply()` simplified the output structure from a list into a **named numeric vector**, which is often more convenient for data analysis.

### (5c) `vapply()`: Vector Apply

**Purpose:** Similar to `sapply()`, but it requires a **template** (`FUN.value`) to be specified for the expected output format. This makes the code safer and faster because R knows in advance the type and length of the result.

```{r part2_5c_vapply}'''
# Define the expected output format: a single numeric value (0.0) for each element
output_template <- c(mean = 0.0)

# Use vapply to calculate the mean of each vector
# If the output didn't match the template (e.g., if one mean returned two numbers), 
# vapply would stop with an error, ensuring data consistency.
vapply_result <- vapply(
  X = data_list,
  FUN = mean,
  FUN.value = output_template # Required template for expected output structure
)

# Display the result
vapply_result

Explanation of Use (5c): vapply() enforced that the result of mean() for every element must be a single numeric value (matching FUN.value = c(mean = 0.0)). It also returned a named numeric vector, similar to sapply(). The primary benefit is safety and reliability: it acts as a check, preventing unexpected output types or lengths, which is critical in robust coding.