Skip to content

Commit

Permalink
Update with bonus lab content
Browse files Browse the repository at this point in the history
  • Loading branch information
aurora-mm committed Nov 5, 2024
1 parent e105d71 commit c4cad31
Show file tree
Hide file tree
Showing 17 changed files with 617 additions and 34 deletions.
16 changes: 11 additions & 5 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Package: LinearRegression
Title: Handling linear regression models
Title: Handling linear and ridge regression models
Version: 1.0
Date: 2024-10-01
Description: This R package provides functionality for handling linear regression
models through the utilization of QR decomposition. This package is a
part of the coursework for the Advanced Programming in R course (732A94) at
Linköping University.
models through the utilization of QR decomposition, as well as ridge regression
models. This package is a part of the coursework for the Advanced Programming
in R course (732A94) at Linköping University.
RoxygenNote: 7.3.2
Encoding: UTF-8
License: GPL-2
Expand All @@ -17,10 +17,16 @@ Roxygen: list(markdown = TRUE)
Suggests:
knitr,
rmarkdown,
mlbench,
caret,
MASS,
testthat (>= 3.0.0)
Config/testthat/edition: 3
Imports:
ggplot2,
stats,
gridExtra
gridExtra,
dplyr,
nycflights13,
rlang
VignetteBuilder: knitr
17 changes: 16 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,45 @@
S3method(coef,linreg)
S3method(plot,linreg)
S3method(pred,linreg)
S3method(print,linreg)
S3method(predict,ridgereg)
S3method(resid,linreg)
S3method(summary,linreg)
export(LiU_theme)
export(coef)
export(linreg)
export(plot)
export(pred)
export(predict)
export(print)
export(resid)
export(ridgereg)
export(summary)
export(visualize_airport_delays)
importFrom(dplyr,"%>%")
importFrom(dplyr,filter)
importFrom(dplyr,group_by)
importFrom(dplyr,inner_join)
importFrom(dplyr,summarize)
importFrom(ggplot2,aes)
importFrom(ggplot2,element_rect)
importFrom(ggplot2,element_text)
importFrom(ggplot2,geom_hline)
importFrom(ggplot2,geom_point)
importFrom(ggplot2,geom_text)
importFrom(ggplot2,ggplot)
importFrom(ggplot2,labs)
importFrom(ggplot2,scale_color_manual)
importFrom(ggplot2,scale_color_viridis_c)
importFrom(ggplot2,scale_size_continuous)
importFrom(ggplot2,stat_summary)
importFrom(ggplot2,theme)
importFrom(ggplot2,theme_grey)
importFrom(ggplot2,theme_minimal)
importFrom(gridExtra,grid.arrange)
importFrom(rlang,.data)
importFrom(stats,median)
importFrom(stats,model.frame)
importFrom(stats,model.matrix)
importFrom(stats,model.response)
importFrom(stats,pt)
importFrom(stats,sd)
10 changes: 5 additions & 5 deletions R/LiU_theme.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
LiU_theme <- function() {
# Return the list
return(list(
ggplot2::theme_grey() +
ggplot2::theme_grey() +
ggplot2::theme(
panel.background = ggplot2::element_rect(fill = "#bde6f6", color = NA),
plot.background = ggplot2::element_rect(fill = "#d2eef9", color = NA),
legend.background = ggplot2::element_rect(fill = "#bde6f6", color = NA)
panel.background = ggplot2::element_rect(fill = "#bde6f6", color = NA),
plot.background = ggplot2::element_rect(fill = "#d2eef9", color = NA),
legend.background = ggplot2::element_rect(fill = "#bde6f6", color = NA)
),
ggplot2::scale_color_manual(values = c("#ff6442", "#8781d3", "#fcf05f", "#687f91"))
))
}
}
33 changes: 25 additions & 8 deletions R/LinearRegression.R
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ print <- function(x) {

#' @rdname print
#'
#' @export
#' @method print linreg
print.linreg <- function(x) {
if (!inherits(x, "linreg")) {
stop("This method is only for objects of class linreg.")
}
cat(paste0("linreg(formula = ", deparse(x$formula), ", data = ", x$name, ")"))
cat("\n\nCoefficients:\n")
cat(names(x$coefficients))
Expand All @@ -84,7 +87,7 @@ print.linreg <- function(x) {
#' Plots the Residuals vs. Fitted & Scale-Location plots with ggplot2.
#'
#' @param x An S3 object of class linreg.
#' @export plot
#' @export
#' @importFrom ggplot2 aes
#' @importFrom ggplot2 geom_point
#' @importFrom ggplot2 geom_hline
Expand All @@ -102,6 +105,9 @@ plot <- function(x) {
#'
#' @export
plot.linreg <- function(x) {
if (!inherits(x, "linreg")) {
stop("This method is only for objects of class linreg.")
}
data <- x$data
y_hat <- x$fitted_values
residuals <- x$residuals
Expand All @@ -115,8 +121,7 @@ plot.linreg <- function(x) {
obs <- 1:length(x$residuals)

# Create data frame for plotting
plot_data <- data.frame(y_hat, residuals, std_residuals, outl, obs
)
plot_data <- data.frame(y_hat, residuals, std_residuals, outl, obs)

# Residuals vs Fitted values
p1 <- ggplot2::ggplot(plot_data, aes(x = y_hat, y = residuals)) +
Expand Down Expand Up @@ -158,7 +163,7 @@ plot.linreg <- function(x) {
#'
#' @param x An S3 object of class linreg.
#' @return A vector of residuals.
#' @export resid
#' @export
resid <- function(x) {
UseMethod("resid")
}
Expand All @@ -167,14 +172,17 @@ resid <- function(x) {
#'
#' @export
resid.linreg <- function(x) {
if (!inherits(x, "linreg")) {
stop("This method is only for objects of class linreg.")
}
return(as.vector(x$residuals))
}

#' Coefficients method for linreg class
#'
#' @param x An S3 object of class linreg.
#' @return A named vector of coefficients.
#' @export coef
#' @export
coef <- function(x) {
UseMethod("coef")
}
Expand All @@ -184,14 +192,17 @@ coef <- function(x) {
#' @export

coef.linreg <- function(x) {
if (!inherits(x, "linreg")) {
stop("This method is only for objects of class linreg.")
}
coeff <- as.vector(x$coefficients)
names(coeff) <- "Coefficients"
return(coeff)
}

#' Summary method for linreg class
#' @param x An S3 object of class linreg.
#' @export summary
#' @export
#' @importFrom stats pt
summary <- function(x) {
UseMethod("summary")
Expand All @@ -202,6 +213,9 @@ summary <- function(x) {
#' @export

summary.linreg <- function(x) {
if (!inherits(x, "linreg")) {
stop("This method is only for objects of class linreg.")
}
# Calculate standard errors, t-values, and p-values
se <- sqrt(diag(x$var_beta))
t_values <- x$coefficients / se
Expand Down Expand Up @@ -245,7 +259,7 @@ summary.linreg <- function(x) {
#' Predicted values method for linreg class
#' @param x An S3 object of class linreg.
#' @return A vector of predicted values.
#' @export pred
#' @export
pred <- function(x) {
UseMethod("pred")
}
Expand All @@ -254,5 +268,8 @@ pred <- function(x) {
#'
#' @export
pred.linreg <- function(x) {
if (!inherits(x, "linreg")) {
stop("This method is only for objects of class linreg.")
}
return(as.vector(x$fitted_values))
}
140 changes: 140 additions & 0 deletions R/RidgeRegression.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#' ridgereg function
#'
#' Performs ridge regression on a given formula and dataset.
#' It normalizes the covariates and calculates the ridge regression coefficients.
#'
#' @param formula A formula object describing the model to be fitted.
#' @param data A data frame containing the variables in the model.
#' @param lambda A numeric value specifying the ridge regularization parameter.
#'
#' @return An S3 object of class ridgereg containing the fitted model.
#'
#' @export ridgereg
#' @importFrom stats model.response
#' @importFrom stats model.frame
#' @importFrom stats sd
#'
ridgereg <- function(formula, data, lambda) {
# Validate the input
if (!inherits(formula, "formula")) {
stop("The formula argument must be a formula object.")
}

if (!is.data.frame(data)) {
stop("The data argument must be a data frame.")
}

if (!is.numeric(lambda)) {
stop("The lambda argument must be numeric.")
}

# Parse the formula and extract the response and predictor variables
X <- model.matrix(formula, data)
y <- model.response(model.frame(formula, data))

# Standardize predictor variables (excluding intercept)
X_mean <- colMeans(X[, -1])
X_sd <- apply(X[, -1], 2, sd)
X[, -1] <- scale(X[, -1], center = X_mean, scale = X_sd)

# Calculate ridge regression coefficients: (X'X + lambda*I)^(-1) X'y
p <- ncol(X)
I_lambda <- diag(lambda, p, p)
I_lambda[1, 1] <- 0 # Do not regularize intercept term

# Ridge regression coefficients
beta <- solve(t(X) %*% X + I_lambda) %*% t(X) %*% y

# Calculate fitted values
fits <- X %*% beta

# Create output object with class ridgereg
ridgereg_obj <- list(
coefficients = beta,
fitted_values = fits,
lambda = lambda,
formula = formula,
data = data,
X_mean = X_mean,
X_sd = X_sd
)

# Assign S3 class "ridgereg" to the output object
class(ridgereg_obj) <- "ridgereg"
return(ridgereg_obj)
}

#' Print method for ridgereg class
#'
#' Prints out the coefficients and coefficient names.
#'
#' @param x An S3 object of class ridgereg.
#' @export print
print <- function(x) {
UseMethod("print")
}

#' @rdname print
#'
#' @method print ridgereg
print.ridgereg <- function(x) {
if (!inherits(x, "ridgereg")) {
stop("This method is only for objects of class ridgereg.")
}
cat("\n\nCall:\n")
cat(paste0("ridgereg(formula = ", deparse(x$formula), ", data = ", x$name, ")"))
cat("\n\nCoefficients:\n")
cat(names(x$coefficients))
cat(paste0("\n", t(x$coefficients)))
}

#' Predict method for ridgereg class
#'
#' Returns the preducted values.
#'
#' @param x An S3 object of class ridgereg.
#' @param newdata A data frame with new data (optional)
#' @export
predict <- function(x, newdata = NULL) {
UseMethod("predict")
}

#' @rdname predict
#'
#' @export
predict.ridgereg <- function(x, newdata = NULL) {
if (!inherits(x, "ridgereg")) {
stop("This method is only for objects of class ridgereg.")
}
if (is.null(newdata)) {
return(x$fitted_values)
} else {
# Normalize the new data using the training data's mean and sd
X_new <- model.matrix(x$formula, newdata)
X_new[, -1] <- scale(X_new[, -1], center = x$X_mean, scale = x$X_sd)

# Predict using the ridge regression coefficients
return(X_new %*% x$coefficients)
}
}

#' Coefficients method for ridgereg class
#'
#' @param x An S3 object of class ridgereg.
#' @return A named vector of coefficients.
#' @export
coef <- function(x) {
UseMethod("coef")
}

#' @rdname coef
#'
#' @method coef ridgereg
coef.ridgereg <- function(x) {
if (!inherits(x, "ridgereg")) {
stop("This method is only for objects of class ridgereg.")
}
coeff <- as.vector(x$coefficients)
names(coeff) <- "Coefficients"
return(coeff)
}
33 changes: 33 additions & 0 deletions R/VisualizeAirportDelays.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#' Visualize Mean Airport Delays by Location
#'
#' Creates a scatter plot that visualizes the mean departure delay of flights
#' at different destination airports across the United States. The plot shows
#' each airport's mean delay by longitude and latitude, with both color and size
#' representing the average delay in minutes.
#'
#' @return A ggplot object representing the mean delays at airports across the United States.
#'
#' @export visualize_airport_delays
#' @importFrom dplyr filter group_by summarize inner_join %>%
#' @importFrom ggplot2 ggplot aes geom_point scale_color_viridis_c scale_size_continuous labs theme_minimal theme
#' @importFrom rlang .data
visualize_airport_delays <- function() {
# Join the flights and airports datasets
delay_data <- nycflights13::flights %>%
filter(!is.na(.data$dep_delay)) %>%
group_by(.data$dest) %>%
summarize(mean_delay = mean(.data$dep_delay, na.rm = TRUE)) %>%
inner_join(nycflights13::airports, by = c("dest" = "faa"))

# Create the plot
ggplot(delay_data, aes(x = .data$lon, y = .data$lat, size = .data$mean_delay, color = .data$mean_delay)) +
geom_point(alpha = 0.7) +
scale_color_viridis_c(option = "C", name = "Mean Delay (min)") +
scale_size_continuous(name = "Mean Delay (min)") +
labs(
title = "Mean Flight Delays by Destination Airport",
x = "Longitude", y = "Latitude"
) +
theme_minimal() +
theme(legend.position = "right")
}
Loading

0 comments on commit c4cad31

Please sign in to comment.