Link to website :
https://rpubs.com/Isaiah-Mireles/1420507
cos_theta <-
function(v1,v2){
as.numeric(v1%*%v2)/(sqrt(sum((v1)^2))*sqrt(sum((v2)^2)))
}
# problem with direction :
# get_angle <- function(v1,v2){acos(cos_theta(v1, v2))*(180/pi)}
get_angle <- function(v1, v2){
angle1 <- atan2(v1[2], v1[1]) * (180/pi) # put each component of vec
angle2 <- atan2(v2[2], v2[1]) * (180/pi)
# compare angle of vec
angle_diff <- angle2 - angle1
# ensure its 0 to 360
angle_diff <- (angle_diff + 360) %% 360
angle_diff
}
Okay, so this question is about the rotation matrix
\[ R(\theta) =\begin{bmatrix}\cos\theta & -\sin\theta \\\sin\theta & \cos\theta\end{bmatrix} \]
unit_vec <- c(1,0) # pointing right
rotate_vector <- function(numeric_vector, degrees){
# check dimension
if( length(numeric_vector) == 2 ){
# convert degrees to radians
theta <- degrees * (pi/180)
# create rotation matrix
rotation_matrix <- matrix(c(cos(theta), -sin(theta),
sin(theta), cos(theta)),
nrow = 2,
byrow = T)
# rotate vector
rotated_vector <- rotation_matrix %*% numeric_vector |> as.vector()
# check angle using get_angle : how much did it rotate?
# copare to i-unit vector pointing right ccw
angle_check <- get_angle(c(1,0), rotated_vector)
return(list(rotated_vector = rotated_vector,
angle_check = angle_check))
} else {
print("Vector must be 2D")
}
}
example <-
rotate_vector(unit_vec, 90)$rotated_vector
rotate_vector(unit_vec, 90)
## $rotated_vector
## [1] 6.123234e-17 1.000000e+00
##
## $angle_check
## [1] 90
rotate_vector(unit_vec, 17)
## $rotated_vector
## [1] 0.9563048 0.2923717
##
## $angle_check
## [1] 17
rotate_vector(unit_vec, 110)
## $rotated_vector
## [1] -0.3420201 0.9396926
##
## $angle_check
## [1] 110
rotate_vector(unit_vec, 270)
## $rotated_vector
## [1] -1.83697e-16 -1.00000e+00
##
## $angle_check
## [1] 270
okay so A is square and so is P
P is orth
\[ \text{Def. } P_{\text{Orth}} \implies P'P=P'P=I \\ \implies P^{-1}=P' \]
all of the columns are orthogonal^
Each feature is a unit vector^
Preserves length & angles under rotation^
an eigen value and vector are
\[ \text{Def. } \lambda \vec{v}=A\vec{v} \]
so in other words, there exists a matrix which scales and/or flips the vector.
eigen vectors are the directions which stay the same after transformation in a matrix
–
\[ \text{Let } A \in \mathbb{R}^{k \times k} \text{ and let } P \in \mathbb{R}^{k \times k} \text{ be orthogonal, so } P^T = P^{-1}. \]
\[ \text{Define } M = P^T A P. \]
\[ \text{Since } P^T = P^{-1}, \text{ we can write} \quad M = P^{-1} A P, \]
\[ \text{so } M \text{ is similar to } A! \]
\[ \text{Let } \lambda \text{ be an eigenvalue of } A \text{ with eigenvector } x \neq 0, \\ \text{ so} \quad Ax = \lambda x. \]
\[ \text{Define } y = P^T x. \]
\[ \text{Since } P \text{ is invertible, } y \neq 0. \]
\[ \text{Now compute:} \quad My = (P^T A P) y = P^T A P (P^T x). \]
\[ \text{Using } PP^T = I, \quad My = P^T A x. \]
\[ \text{Substitute } Ax = \lambda x: \quad My = P^T (\lambda x) = \lambda P^T x = \lambda y. \]
\[ \text{Thus, } y \text{ is an eigenvector of } M \text{ with eigenvalue } \lambda. \]
\[ \text{Therefore, every eigenvalue of } A \text{ is an eigenvalue of } P^T A P. \]
\[ \text{By symmetry (reversing the argument), they have the same eigenvalues.} \]
r1 <- c(5, -sqrt(3))
r2 <- c(-sqrt(3), 7)
m <- matrix(c(r1,r2), nrow=2, byrow = T)
m
## [,1] [,2]
## [1,] 5.000000 -1.732051
## [2,] -1.732051 7.000000
det <- det(m); det
## [1] 32
trace <- sum(diag(m)); trace
## [1] 12
eigen_val <- (trace + sqrt(trace^2 - 4*det(m))*c(1,-1))/2
eigen_val
## [1] 8 4
m - 4*diag(1,2)
## [,1] [,2]
## [1,] 1.000000 -1.732051
## [2,] -1.732051 3.000000
so as we can see that our eigen vectors are just gonna be a scalar multiple of what we got before :
by adjusting \(\frac{c}{\sqrt{\lambda}}\) we obtain the
correctly scaled vectors :
\[ \text{For : } c^2=1 \\ \implies \\ \boxed{ \vec{v}_1=<\frac{\sqrt{3}}{4},\frac{1}{4}> \\ \text{and,} \\ \vec{v}_2 = <\frac{1}{4\sqrt{2}},-\frac{1}{4\sqrt{2}}> } \]
\[ \text{For : } c^2=\pi \\ \implies \\ \boxed{ \vec{v}_1= <\frac{\pi\sqrt{3}}{4},\frac{\pi}{4}>\\ \text{and,} \\ \vec{v}_2 = <\frac{\pi}{4\sqrt{2}},-\frac{\pi \sqrt{3}}{4\sqrt{2}}> } \]
Recall :
\[ \hat{\beta} = (X'X)^{-1}X'\vec{y} \]
Where \(X\) is our design matrix : \(X=[\vec{1} \ \vec{x}]\)
# getwd()
df <- read.csv("data1.csv")
Therefore :
intercept <- rep(1, nrow(df))
design_mat <- cbind(intercept, df$x)
y <- df$y
beta_hat <-
solve(t(design_mat)%*%design_mat)%*%t(design_mat)%*%y
mdl <- lm(y~x, data=df)
summary(mdl)$coefficients[,1]
## (Intercept) x
## -4.269400 4.485172
beta_hat
## [,1]
## intercept -4.269400
## 4.485172
plot(df$x, df$y)
abline(mdl, col = "red")
x <- df$x
# ?poly
model <- lm(y ~ poly(x, degree = 6, raw = T), data = df)
model2 <- lm(y ~ x + I(x^2) + I(x^3) + I(x^4) + I(x^5) + I(x^5) + I(x^6), data = df)
poly() function – the preset is raw = F so it
makes each regressor orthogonal. This is not the same as just the other
version using I()print("Polyn Reg")
## [1] "Polyn Reg"
summary(model)$r.squared
## [1] 0.8254
print("Linear Reg")
## [1] "Linear Reg"
summary(mdl)$r.squared
## [1] 0.4777358
plot(x,y)
lines(smooth.spline(x, predict(model)), col = "red")
abline(mdl, col = "blue")
library(tidymodels)
library(recipes)
# 1. Create LOOCV
loocv_folds <- vfold_cv(df, v = nrow(df)) # folds = sample sz
# 2. Define recipe with a tunable degree for a polynomial
poly_rec <- recipe(y ~ x, data = df) %>%
step_poly(x, degree = tune()) # Tune the degree
# 3. Model specification
poly_spec <- linear_reg() %>% set_engine("lm")
# 4. Workflow
poly_wf <- workflow() %>%
add_recipe(poly_rec) %>%
add_model(poly_spec)
# 5. Tune grid (testing degrees 1 through 6)
degree_grid <- grid_regular(degree(range = c(1, 6)), levels = 6)
tune_results <- tune_grid(
poly_wf,
resamples = loocv_folds,
grid = degree_grid
)
# 6. Select best model
best_poly <- select_best(tune_results, metric = "rmse")
mdl_metrics <-
collect_metrics(tune_results) |> filter(.metric=="rmse") |> select(degree, .metric, mean, std_err)
mdl_metrics
## # A tibble: 6 × 4
## degree .metric mean std_err
## <dbl> <chr> <dbl> <dbl>
## 1 1 rmse 12.3 0.973
## 2 2 rmse 12.3 0.841
## 3 3 rmse 8.51 0.455
## 4 4 rmse 8.60 0.468
## 5 5 rmse 8.60 0.435
## 6 6 rmse 8.62 0.439
poly3_mdl <- lm(y ~ poly(x, degree = 3, raw = T), data = df)
poly6_mdl <- lm(y ~ poly(x, degree = 6, raw = T), data = df)
plot(x,y)
lines(smooth.spline(x, predict(poly3_mdl)), col = "red")
lines(smooth.spline(x, predict(poly6_mdl)), col = "green")
abline(mdl, col = "blue")
Linear regression : BLUE
Polynomial regression – degree 3 : RED
Polynomial regression – degree 6 : GREEN
mdl_metrics[c(3,6),]
## # A tibble: 2 × 4
## degree .metric mean std_err
## <dbl> <chr> <dbl> <dbl>
## 1 3 rmse 8.51 0.455
## 2 6 rmse 8.62 0.439
std_err and
mean (rsme) when degree 3 hitspaste0("poly3_mdl :",summary(poly3_mdl)$r.squared)
## [1] "poly3_mdl :0.820499460621341"
paste0("poly6_mdl :",summary(poly6_mdl)$r.squared)
## [1] "poly6_mdl :0.825399979221013"
round(summary(poly6_mdl)$r.squared - summary(poly3_mdl)$r.squared , 3)
## [1] 0.005
incomplete!!!!
need to fix radians, degrees output
does handle above 180 degrees properly
graph_vector2D <- function(v1, v2) {
# Determine plot limits
x_limits <- range(c(0, v1[1], v2[1]))
y_limits <- range(c(0, v1[2], v2[2]))
# Create an empty plot
plot(
NA,
xlim = x_limits,
ylim = y_limits,
xlab = "X-axis",
ylab = "Y-axis",
main = "2D Vector Plot",
asp = 1
)
# Add grid and axes
grid()
abline(h = 0, v = 0, col = "gray")
# Draw vectors from origin
arrows(
x0 = 0, y0 = 0,
x1 = v1[1], y1 = v1[2],
col = "blue", lwd = 2, length = 0.1
)
arrows(
x0 = 0, y0 = 0,
x1 = v2[1], y1 = v2[2],
col = "red", lwd = 2, length = 0.1
)
# Add labels near the vector tips
text(v1[1], v1[2], labels = "v1", pos = 4, col = "blue")
text(v2[1], v2[2], labels = "v2", pos = 4, col = "red")
}
# use case :
graph_vector2D(-c(0,1),c(-1,0))
graph_vector3D <- function(v1, v2) {
# Load required package
if (!requireNamespace("plotly", quietly = TRUE)) {
stop("The 'plotly' package is required. Please install it using install.packages('plotly').")
}
# Helper function to add arrowheads using cones
create_arrowhead <- function(plot, vec, color) {
plotly::add_trace(
plot,
type = "cone",
x = vec[1],
y = vec[2],
z = vec[3],
u = vec[1],
v = vec[2],
w = vec[3],
sizemode = "absolute",
sizeref = 0.4,
anchor = "tip",
showscale = FALSE,
colorscale = list(c(0, color), c(1, color)),
hoverinfo = "none"
)
}
# Create base plot with vector shafts
plot <- plotly::plot_ly() |>
plotly::add_trace(
x = c(0, v1[1]),
y = c(0, v1[2]),
z = c(0, v1[3]),
type = "scatter3d",
mode = "lines+text",
line = list(color = "blue", width = 6),
text = c("", "v1"),
textposition = "top center",
name = "v1"
) |>
plotly::add_trace(
x = c(0, v2[1]),
y = c(0, v2[2]),
z = c(0, v2[3]),
type = "scatter3d",
mode = "lines+text",
line = list(color = "red", width = 6),
text = c("", "v2"),
textposition = "top center",
name = "v2"
)
# Add arrowheads correctly
plot <- create_arrowhead(plot, v1, "blue")
plot <- create_arrowhead(plot, v2, "red")
# Add layout settings
plot <- plotly::layout(
plot,
title = "3D Vector Plot",
scene = list(
xaxis = list(title = "X-axis"),
yaxis = list(title = "Y-axis"),
zaxis = list(title = "Z-axis")
)
)
return(plot)
}
# use case :
# Plot using your function
graph_vector3D(c(1, 0, 0), c(0, 1, 0))
graph_vector <- function(v1, v2,
table_position = "topright",
docu = FALSE) {
# -------------------------
# Documentation Mode
# -------------------------
if (docu) {
cat("
graph_vector(v1, v2, table_position = 'topright', docu = FALSE)
Description:
Plots two vectors in 2D or 3D (dimension must be < 4).
Automatically computes and displays:
- cos(theta)
- theta in radians
- theta in degrees
Parameters:
v1 Numeric vector (length 2 or 3).
v2 Numeric vector (same dimension as v1).
table_position Character string specifying where the
angle information appears.
Possible values:
'topright'
'topleft'
'bottomleft'
'bottomright'
docu Logical (TRUE/FALSE).
If TRUE, prints this documentation only.
Output:
- 2D vectors → Static base R plot.
- 3D vectors → Interactive Plotly plot.
Examples:
graph_vector(c(1,0), c(0,1))
graph_vector(c(1,0,0), c(0,1,0), table_position='bottomleft')
")
return(invisible(NULL))
}
# -------------------------
# Validation
# -------------------------
if (!is.numeric(v1) || !is.numeric(v2)) {
stop("Both v1 and v2 must be numeric vectors.")
}
if (length(v1) != length(v2)) {
stop("v1 and v2 must have the same dimension.")
}
dim <- length(v1)
if (dim >= 4) {
stop("Vectors must have dimension less than 4 (2D or 3D only).")
}
valid_positions <- c(
"topright", "topleft",
"bottomleft", "bottomright"
)
if (!(table_position %in% valid_positions)) {
stop("Invalid table_position value.")
}
# -------------------------
# Compute angle info
# -------------------------
cos_val <- cos_theta(v1, v2)
angle_rad <- get_angle(v1, v2)
angle_deg <- angle_rad * 180 / pi
info_text <- c(
paste0("cos(theta) = ", round(cos_val, 4)),
paste0("theta (rad) = ", round(angle_rad, 4)),
paste0("theta (deg) = ", round(angle_deg, 2))
)
# -------------------------
# 2D Case
# -------------------------
if (dim == 2) {
graph_vector2D(v1, v2)
legend(
table_position,
legend = info_text,
bty = "n"
)
# -------------------------
# 3D Case
# -------------------------
} else if (dim == 3) {
plot <- graph_vector3D(v1, v2)
pos_map <- list(
topright = list(x = 1, y = 1),
topleft = list(x = 0, y = 1),
bottomleft = list(x = 0, y = 0),
bottomright = list(x = 1, y = 0)
)
coords <- pos_map[[table_position]]
plot <- plotly::layout(
plot,
annotations = list(
list(
x = coords$x,
y = coords$y,
xref = "paper",
yref = "paper",
text = paste(info_text, collapse = "<br>"),
showarrow = FALSE,
align = "left"
)
)
)
return(plot)
}
}
# Use cases :
graph_vector(c(0, -1), c(-1, 0))
graph_vector(
c(2, 3, 1),
c(3, -2, 0),
table_position = "bottomleft"
)
v1 <- c(1, 0)
v2 <- c(0, 1)
graph_vector(v1, v2, table_position = "topright")
graph_vector(docu = TRUE)
##
## graph_vector(v1, v2, table_position = 'topright', docu = FALSE)
##
## Description:
## Plots two vectors in 2D or 3D (dimension must be < 4).
## Automatically computes and displays:
## - cos(theta)
## - theta in radians
## - theta in degrees
##
## Parameters:
## v1 Numeric vector (length 2 or 3).
## v2 Numeric vector (same dimension as v1).
## table_position Character string specifying where the
## angle information appears.
##
## Possible values:
## 'topright'
## 'topleft'
## 'bottomleft'
## 'bottomright'
##
## docu Logical (TRUE/FALSE).
## If TRUE, prints this documentation only.
##
## Output:
## - 2D vectors → Static base R plot.
## - 3D vectors → Interactive Plotly plot.
##
## Examples:
## graph_vector(c(1,0), c(0,1))
## graph_vector(c(1,0,0), c(0,1,0), table_position='bottomleft')
# Base vector
y1 <- c(1, 0)
# Opposite direction
y2 <- c(-1, 0)
# Mostly opposite
y3 <- c(-1, 1)
# Another opposite-ish
y4 <- c(-2, -1)
# Slightly opposite
y5 <- c(-0.5, 0.2)
graph_vector(y1, y2)
graph_vector(y1, y3)
graph_vector(y1, y4, table_position="bottomright")
graph_vector(y1, y5)
graph_vector(unit_vec, example)
graph_vector(unit_vec, rotate_vector(unit_vec, 270)$rotated_vector)