#------------------------------------------
# Load required packages
#------------------------------------------
library(MASS)
library(nlme)
library(betareg)
library(survival)
library(lme4)
library(glmmTMB)
library(mgcv)
#------------------------------------------
# Simulate dataset
#------------------------------------------
set.seed(123)
n <- 100
x1 <- rnorm(n)
x2 <- rnorm(n)
x3 <- runif(n, 0, 5)
x4 <- factor(sample(letters[1:3], n, replace = TRUE))
group_levels <- paste0("G", 1:10)
group <- factor(sample(group_levels, n, replace = TRUE))
# Generate random intercepts for each group
group_effects <- rnorm(length(group_levels), mean = 0, sd = 2) # non-zero variance
names(group_effects) <- group_levels
group_intercept <- group_effects[as.character(group)]
# Non-linear continuous response
true_y <- 5 * sin(x3) + 3 * x1 + group_intercept + model.matrix(~x4)[, -1] %*% c(2, -2)
noise <- rnorm(n, sd = 3)
y <- as.vector(true_y + noise)
# Binary response with group effect added to logit
logit_p <- 2 * x1 - 1 + group_intercept
p <- 1 / (1 + exp(-logit_p))
binary_y <- rbinom(n, size = 1, prob = p)
# Binomial response: number of successes and failures
y3 <- sample(10:30, n, replace = TRUE)
logit_p_prop <- -1.5 * scale(x1)
p_prop <- 1 / (1 + exp(-logit_p_prop))
y1 <- rbinom(n, size = y3, prob = p_prop) # successes
y2 <- y3 - y1 # failures
# Count response with group effect in log(mu)
mu_count <- exp(1 + 0.8 * x2 - 0.5 * (x4 == "b") + group_intercept)
size <- 1.2
count_y <- rnbinom(n, size = size, mu = mu_count)
# Offset variable
exposure <- runif(n, 1, 10)
# Assemble dataset
sim.data <- data.frame(x1, x2, x3, x4, group, y, binary_y, y1, y2, y3, count_y, exposure)
#------------------------------------------
# 1. Linear model (lm)
#------------------------------------------
mod.lm <- lm(y ~ x1 + x4,
data = sim.data)
easyViz(model = mod.lm, data = sim.data, predictor = "x1",
by = "x4",
pred_range_limit = FALSE,
pred_on_top = TRUE,
ylim = c(-12,18),
xlab = "Predictor x1",
ylab = "Response y",
point_col = ifelse(sim.data$x4=="a", "red",
ifelse(sim.data$x4=="b", "orange",
"yellow")),
point_cex = 0.5,
pred_line_col = c("red", "orange", "yellow"),
pred_line_lty = 1,
ci_polygon_col = c(rgb(1,0,0,0.5),
rgb(1,0.5,0,0.5),
rgb(1,1,0,0.5)))
# Numeric x categorical interaction
# Backtransform response
# Show conditioning summary
mod.lm2 <- lm(sqrt(x3) ~ x1 * x4,
data = sim.data)
easyViz(model = mod.lm2, data = sim.data, predictor = "x1",
by="x4",
pred_transform = function(x) x^2,
ylim = c(0,8),
show_data_points = FALSE,
show_conditioning = TRUE)
# Polynomial terms
mod.lm3 <- lm(y ~ poly(x3, 3),
data = sim.data)
easyViz(model = mod.lm3, data = sim.data, predictor = "x3",
pred_on_top = TRUE,
font_family = "mono",
point_col = rgb(1,0,0,0.3),
point_pch = "+",
ci_level = 0.85,
ci_type = "lines",
ci_line_lty = 2)
# Extract prediction data
df.mod.lm <- easyViz(model = mod.lm, data = sim.data, predictor = "x1",
by = "x4", ci_level = 0.85, plot = FALSE)
head(df.mod.lm)
#------------------------------------------
# 2. Robust linear model (rlm)
#------------------------------------------
mod.rlm <- rlm(y ~ x1 + x4,
data = sim.data)
# Add legend outside of plotting region
old_xpd_mar <- par(xpd = TRUE, mar = c(5.1, 4.1, 4.1, 5.1))
easyViz(model = mod.rlm, data = sim.data, predictor = "x1",
by = "x4",
pred_on_top = TRUE,
bty = "n",
xlab = "Predictor x1",
ylab = "Response y",
point_col = ifelse(sim.data$x4=="a", "red",
ifelse(sim.data$x4=="b", "orange",
"yellow")),
point_cex = 0.5,
pred_line_col = c("red", "orange", "yellow"),
pred_line_lty = 1,
ci_polygon_col = c(rgb(1,0,0),
rgb(1,0.5,0),
rgb(1,1,0)),
ci_polygon_alpha = 0.4,
legend_position = c(2.25,13),
legend_title = "Predictor x4",
legend_title_size = 0.9,
legend_args = list(legend = c("a", "b", "c"),
col = c("red", "orange", "yellow"),
lty = c(1, 1, 1),
lwd = c(2, 2, 2),
pch = c(16, 16, 16),
cex = 0.75,
bty = "n"))
par(old_xpd_mar)
#------------------------------------------
# 3. Generalized least squares (gls)
#------------------------------------------
mod.gls <- gls(y ~ x1 + x2 + x4,
correlation = corAR1(form = ~1|group),
data = sim.data)
easyViz(model = mod.gls, data = sim.data, predictor = "x4",
jitter_data_points = TRUE,
bty = "n",
xlab = "Predictor x4",
ylab = "Response y",
point_col = rgb(0,0,1,0.2),
pred_point_col = "blue",
cat_labels = c("group A", "group B", "group C"))
# Categorical x categorical interaction & outer legend
sim.data$x5 <- sample(c(rep("CatA", 50), rep("CatB", 50)))
mod.gls2 <- gls(y ~ x1 + x2 + x4 * x5,
correlation = corAR1(form = ~1|group),
data = sim.data)
old_xpd_mar <- par(xpd = TRUE, mar = c(5.1, 4.1, 4.1, 5.1))
easyViz(model = mod.gls2, data = sim.data, predictor = "x4",
by = "x5",
jitter_data_points = TRUE,
ylim = c(-15,15),
xlab = "Predictor x4",
ylab = "Response y",
cat_labels = c("group A", "group B", "group C"),
point_col = c(rgb(0,0,1,0.2), rgb(1,0,0,0.2)),
pred_point_col = c("blue", "red"),
ci_bar_col = c("blue", "blue", "blue", "red", "red", "red"),
ci_bar_caps = 0,
legend_position = c(3.4, 15),
legend_args = list(title = "Pred x5",
title.cex = 1,
legend = c("A", "B"),
pt.cex = 1.25,
horiz = TRUE,
inset = c(-0.2, 0)))
par(old_xpd_mar)
#------------------------------------------
# 4. Nonlinear least squares (nls)
#------------------------------------------
mod.nls <- nls(y ~ a * sin(b * x3) + c,
data = sim.data,
start = list(a = 5, b = 1, c = 0))
summary(mod.nls)
easyViz(model = mod.nls, data = sim.data, predictor = "x3",
pred_on_top = TRUE,
font_family = "serif",
bty = "n",
xlab = "Predictor x3",
ylab = "Response y",
point_col = rgb(0,1,0,0.7),
point_pch = 1,
ci_type = "lines",
ci_line_col = "black",
ci_line_lty = 2)
text(x = 2.5, y = 11,
labels = expression(Y %~% 5.31584 %*% sin(1.08158 %*% X[3]) + 0.51338),
cex = 0.7)
#------------------------------------------
# 5. Generalized linear model (glm)
#------------------------------------------
mod.glm <- glm(binary_y ~ x1 + x4 + offset(log(exposure)),
family = binomial(link="cloglog"),
data = sim.data)
easyViz(model = mod.glm, data = sim.data, predictor = "x1",
fix_values = list(x4="b", exposure=1),
xlab = "Predictor x1",
ylab = "Response y",
binary_data_type = "binned",
point_col = "black",
ci_polygon_col = "red",
ci_polygon_alpha = 1)
# Customize data points
easyViz(model = mod.glm, data = sim.data, predictor = "x4",
bty = "n",
xlab = "Predictor x4",
ylab = "Response y",
binary_data_type = "plain",
jitter_data_points = TRUE,
point_col = "black",
point_pch = "|",
point_cex = 0.5)
# Binomial glm for proportion data
mod.glm2 <- glm(y1/y3 ~ x1 + x4, weights = y3,
family = binomial(link="logit"),
data = sim.data)
easyViz(model = mod.glm2, data = sim.data, predictor = "x1",
pred_on_top = TRUE,
xlab = "Predictor x1",
ylab = "Response y",
point_col = "black",
ci_polygon_col = "red")
# Transform response predictions to percentage
easyViz(model = mod.glm2, data = sim.data, predictor = "x1",
pred_transform = function(x) 100 * x,
pred_on_top = TRUE,
xlab = "Predictor x1",
ylab = "Response y",
show_data_points = FALSE,
point_col = "black",
ci_polygon_col = "red",
plot_args = list(yaxt = "n"))
axis(2, at = pretty(par("usr")[3:4]),
labels = paste0(pretty(par("usr")[3:4]), "%"),
las = 1)
#------------------------------------------
# 6. Negative binomial GLM (glm.nb)
#------------------------------------------
mod.glm.nb <- glm.nb(count_y ~ x2 + offset(log(exposure)),
data = sim.data)
easyViz(model = mod.glm.nb, data = sim.data, predictor = "x2",
font_family = "mono",
bty = "L",
plot_args = list(main = "NB model"),
xlab = "Predictor x2",
ylab = "Response y",
ci_polygon_col = "blue")
#------------------------------------------
# 7. Beta regression (betareg)
#------------------------------------------
sim.data$prop <- y1/y3
mod.betareg <- betareg(prop ~ x1 * x4, offset = log(exposure),
data = sim.data, link= "cloglog")
easyViz(model = mod.betareg, data = sim.data, predictor = "x1",
fix_values = c(exposure = 6),
xlab = "Predictor x1",
ylab = "Response y",
ci_polygon_col = "forestgreen",
show_conditioning = TRUE)
#------------------------------------------
# 8. Survival model (coxph)
#------------------------------------------
mod.surviv <- coxph(Surv(y3, binary_y) ~ poly(x1,2) + x4, data=sim.data)
easyViz(model = mod.surviv, data = sim.data, predictor = "x1",
pred_type = "link",
xlab = "Predictor x1",
ci_polygon_col = "orange2",
ci_polygon_alpha = 1,
show_conditioning = TRUE)
#------------------------------------------
# 9. Linear mixed model (lmer)
#------------------------------------------
mod.lmer <- lmer(y ~ x1 + x4 + (1 | group),
data = sim.data)
# Random terms and population-level prediction
easyViz(model = mod.lmer, data = sim.data, predictor = "x1",
by="group",
re_form = NULL,
bty = "n",
plot_args = list(xaxp = c(round(min(sim.data$x1),1),
round(max(sim.data$x1),1), 5)),
ylim = c(-15, 15),
xlab = "Predictor x1",
ylab = "Response y",
pred_line_col = "green",
pred_line_lty = 1,
pred_line_lwd = 1,
add_legend = FALSE)
old_new <- par(new = TRUE)
easyViz(model = mod.lmer, data = sim.data, predictor = "x1",
re_form = NA,
bty = "n",
plot_args = list(xaxp = c(round(min(sim.data$x1),1),
round(max(sim.data$x1),1), 5)),
show_data_points = FALSE,
xlab = "Predictor x1",
ylab = "Response y",
ylim = c(-15, 15),
pred_line_col = "red",
pred_line_lty = 1,
pred_line_lwd = 2,
ci_type = NULL)
par(old_new)
#------------------------------------------
# 10. Generalized linear mixed model (glmer)
#------------------------------------------
mod.glmer <- glmer(binary_y ~ x1 + x4 + (1 | group),
family = binomial,
data = sim.data)
# Random terms
easyViz(model = mod.glmer, data = sim.data, predictor = "x1",
by = "group",
re_form = NULL,
cat_conditioning = "reference",
font_family = "serif",
xlab = "Predictor x1",
ylab = "Response y",
binary_data_type = "binned",
pred_range_limit = FALSE,
pred_line_col = 1:10,
pred_line_lty = 1:10,
pred_line_lwd = 1,
legend_args = list(ncol = 5)) # adjust legend columns
# Extract prediction data & show conditioning summary
df.mod.glmer <- easyViz(model = mod.glmer, data = sim.data, predictor = "x1",
by = "group", re_form = NULL, cat_conditioning = "reference",
show_conditioning = TRUE, plot = FALSE)
head(df.mod.glmer)
#------------------------------------------
# 11. GLMM with negative binomial (glmer.nb)
#------------------------------------------
mod.glmer.nb <- glmer.nb(count_y ~ x2 + x4 + (1 | group),
data = sim.data)
easyViz(model = mod.glmer.nb, data = sim.data, predictor = "x2",
re_form = NA,
bty = "n",
xlab = "Predictor x2",
ylab = "Response y",
ylim = c(0, 120),
point_pch = 1)
#------------------------------------------
# 12. GLMM (glmmTMB)
#------------------------------------------
mod.glmmTMB <- glmmTMB(count_y ~ x2 + x4 + (1 | group),
ziformula = ~ x2,
family = nbinom2,
data = sim.data)
# Random terms with confidence bands
easyViz(model = mod.glmmTMB, data = sim.data, predictor = "x2",
re_form = NULL, by= "group",
bty = "n",
xlab = "Predictor x2",
ylab = "Response y",
show_data_points = FALSE,
pred_line_col = 1:10,
ci_polygon_col = 1:10,
legend_args = list(ncol = 5)) # adjust legend columns
#------------------------------------------
# 13. GAM (mgcv::gam) with random smooth
#------------------------------------------
mod.gam <- gam(y ~ s(x3) + s(group, bs = "re"),
data = sim.data)
# Multiple confidence levels
easyViz(model = mod.gam, data = sim.data, predictor = "x3",
re_form = NA,
las = 0,
plot_args = list(xlab = "", ylab = "", axes = FALSE),
bty = "n",
xlab = "Predictor x3",
ylab = "Response y",
point_col = "black",
point_pch = 1,
ci_level = 0.99,
ci_polygon_alpha = 0.25,
ci_polygon_col = "red")
old_new <- par(new = TRUE)
easyViz(model = mod.gam, data = sim.data, predictor = "x3",
re_form = NA,
las = 0,
plot_args = list(xlab = "", ylab = "", axes = FALSE),
bty = "n",
xlab = "Predictor x3",
ylab = "Response y",
point_col = "black",
point_pch = 1,
ci_level = 0.95,
ci_polygon_alpha = 0.5,
ci_polygon_col = "red")
par(old_new)
old_new <- par(new = TRUE)
easyViz(model = mod.gam, data = sim.data, predictor = "x3",
re_form = NA,
las = 0,
bty = "n",
xlab = "Predictor x3",
ylab = "Response y",
point_col = "black",
point_pch = 1,
ci_polygon_alpha = 1,
ci_level = 0.8,
ci_polygon_col = "red")
par(old_new)
rect(3.5,9,4,9.5, col=adjustcolor("red", alpha.f = 0.25), border=FALSE)
rect(3.5,7.5,4,8, col=adjustcolor("red", alpha.f = 0.5), border=FALSE)
rect(3.5,6,4,6.5, col=adjustcolor("red", alpha.f = 1), border=FALSE)
text(c(4.4, 4.4, 4.4), c(9.25, 7.75, 6.25), c("99% CI", "95% CI", "80% CI"), cex=0.75)
#------------------------------------------
# 14. Plotting 3-way interaction
#------------------------------------------
mod.lm.int <- lm(y ~ x1 * x2 * x3,
data = sim.data)
# Check conditional values to use for plotting
quantile(x2, c(0.1,0.5, 0.9))
quantile(x3, c(0.1,0.5, 0.9))
# (optional) Generate a customizable function to add a strip label at the top
add_strip_label <- function(label, bg = "grey90", cex = 1, font = 2, height_mult = 2.5) {
usr <- par("usr")
x_left <- usr[1]
x_right <- usr[2]
y_top <- usr[4]
# Estimate strip height using text height
h <- strheight(label, cex = cex) * height_mult
# Strip coordinates (extending above the plotting region)
y_bottom <- y_top + 0.2 * h
y_top_box <- y_bottom + h
# Draw the full-width strip
rect(x_left, y_bottom, x_right, y_top_box, col = bg, border = "black", xpd = NA)
# Add centered text
text(x = mean(c(x_left, x_right)),
y = mean(c(y_bottom, y_top_box)),
labels = label, cex = cex, font = font, xpd = NA)
}
# par settings for multi-panel plot
old_mfrow <- par(mfrow = c(1, 3))
old_oma <- par(oma = c(4, 4, 2, 1))
old_mar <- par(mar = c(0, 0, 2, 0))
# Panel 1
easyViz(model = mod.lm.int, data = sim.data, predictor = "x1",
by = "x2",
fix_values = c(x3 = 0.5750978),
plot_args = list(xlab = "", ylab = ""),
show_data_points = FALSE,
pred_line_col = c(2, 3, 4),
ci_polygon_col = c(2, 3, 4),
legend_position = "topleft",
legend_title = NULL,
legend_labels = c("x2 = -1.3", "x2 = -0.2", "x2 = 1.5"))
add_strip_label("x3 = 0.6")
mtext("Response y", side = 2, outer = TRUE, line = 2.5)
# Panel 2
easyViz(model = mod.lm.int, data = sim.data, predictor = "x1",
by = "x2",
fix_values = c(x3 = 2.3095046),
plot_args = list(yaxt = "n", xlab = "", ylab = ""),
show_data_points = FALSE,
pred_line_col = c(2, 3, 4),
ci_polygon_col = c(2, 3, 4),
add_legend = FALSE)
add_strip_label("x3 = 2.3")
# Panel 3
easyViz(model = mod.lm.int, data = sim.data, predictor = "x1",
by = "x2",
fix_values = c(x3 = 4.4509078),
plot_args = list(yaxt = "n", xlab = "", ylab = ""),
show_data_points = FALSE,
pred_line_col = c(2, 3, 4),
ci_polygon_col = c(2, 3, 4),
add_legend = FALSE)
add_strip_label("x3 = 4.5")
mtext("Predictor x1", side = 1, outer = TRUE, line = 2.5)
# Restore original settings
par(old_mfrow)
par(old_oma)
par(old_mar)
#-------------END OF EXAMPLES--------------
Run the code above in your browser using DataLab