Dr. Debashis Chatterjee
Assistant Professor, Dept. of Statistics, Visva‑Bharati
University
A focused R‑notebook analysing the unpublished Greenland Summit firn‑air data (Severinghaus 2010‑010) — from basic EDA to advanced inference, with commentary in .
options(repos = c(CRAN = "https://cloud.r-project.org"))
core_pkgs <- c("tidyverse", "lubridate", "janitor", "patchwork", "GGally",
"changepoint", "factoextra", "lme4", "ggfortify", "broom")
needed <- setdiff(core_pkgs, rownames(installed.packages()))
if (length(needed)) install.packages(needed, quiet = TRUE)
lapply(core_pkgs, library, character.only = TRUE)
## Warning: package 'ggplot2' was built under R version 4.4.3
## Warning: package 'janitor' was built under R version 4.4.3
## Warning: package 'GGally' was built under R version 4.4.1
## Warning: package 'changepoint' was built under R version 4.4.3
## Warning: package 'factoextra' was built under R version 4.4.1
## Warning: package 'lme4' was built under R version 4.4.1
## Warning: package 'ggfortify' was built under R version 4.4.3
## Warning: package 'broom' was built under R version 4.4.3
## [[1]]
## [1] "lubridate" "forcats" "stringr" "dplyr" "purrr" "readr"
## [7] "tidyr" "tibble" "ggplot2" "tidyverse" "stats" "graphics"
## [13] "grDevices" "utils" "datasets" "methods" "base"
##
## [[2]]
## [1] "lubridate" "forcats" "stringr" "dplyr" "purrr" "readr"
## [7] "tidyr" "tibble" "ggplot2" "tidyverse" "stats" "graphics"
## [13] "grDevices" "utils" "datasets" "methods" "base"
##
## [[3]]
## [1] "janitor" "lubridate" "forcats" "stringr" "dplyr" "purrr"
## [7] "readr" "tidyr" "tibble" "ggplot2" "tidyverse" "stats"
## [13] "graphics" "grDevices" "utils" "datasets" "methods" "base"
##
## [[4]]
## [1] "patchwork" "janitor" "lubridate" "forcats" "stringr" "dplyr"
## [7] "purrr" "readr" "tidyr" "tibble" "ggplot2" "tidyverse"
## [13] "stats" "graphics" "grDevices" "utils" "datasets" "methods"
## [19] "base"
##
## [[5]]
## [1] "GGally" "patchwork" "janitor" "lubridate" "forcats" "stringr"
## [7] "dplyr" "purrr" "readr" "tidyr" "tibble" "ggplot2"
## [13] "tidyverse" "stats" "graphics" "grDevices" "utils" "datasets"
## [19] "methods" "base"
##
## [[6]]
## [1] "changepoint" "zoo" "GGally" "patchwork" "janitor"
## [6] "lubridate" "forcats" "stringr" "dplyr" "purrr"
## [11] "readr" "tidyr" "tibble" "ggplot2" "tidyverse"
## [16] "stats" "graphics" "grDevices" "utils" "datasets"
## [21] "methods" "base"
##
## [[7]]
## [1] "factoextra" "changepoint" "zoo" "GGally" "patchwork"
## [6] "janitor" "lubridate" "forcats" "stringr" "dplyr"
## [11] "purrr" "readr" "tidyr" "tibble" "ggplot2"
## [16] "tidyverse" "stats" "graphics" "grDevices" "utils"
## [21] "datasets" "methods" "base"
##
## [[8]]
## [1] "lme4" "Matrix" "factoextra" "changepoint" "zoo"
## [6] "GGally" "patchwork" "janitor" "lubridate" "forcats"
## [11] "stringr" "dplyr" "purrr" "readr" "tidyr"
## [16] "tibble" "ggplot2" "tidyverse" "stats" "graphics"
## [21] "grDevices" "utils" "datasets" "methods" "base"
##
## [[9]]
## [1] "ggfortify" "lme4" "Matrix" "factoextra" "changepoint"
## [6] "zoo" "GGally" "patchwork" "janitor" "lubridate"
## [11] "forcats" "stringr" "dplyr" "purrr" "readr"
## [16] "tidyr" "tibble" "ggplot2" "tidyverse" "stats"
## [21] "graphics" "grDevices" "utils" "datasets" "methods"
## [26] "base"
##
## [[10]]
## [1] "broom" "ggfortify" "lme4" "Matrix" "factoextra"
## [6] "changepoint" "zoo" "GGally" "patchwork" "janitor"
## [11] "lubridate" "forcats" "stringr" "dplyr" "purrr"
## [16] "readr" "tidyr" "tibble" "ggplot2" "tidyverse"
## [21] "stats" "graphics" "grDevices" "utils" "datasets"
## [26] "methods" "base"
Data Source: Unpublished Greenland Summit firn-air dataset (Severinghaus 2010-010) from NOAA Paleoclimatology.
Cleaning Process:
- Converted dates with lubridate::mdy()
- Replaced sentinel values (“a” and “9.999”) with NA
- Coerced depth and isotopic measurements to numeric
- Arranged by depth to reflect firn column ordering
Key Observation:
Monotonic increase of \(\delta^{18}O\)
with depth (\(\hat\beta_1 = 0.0040\text{‰
m}^{-1}\)) confirms gravitational fractionation:
\[
\delta^{18}O(z) \approx \delta_0 + \beta_1 z
\] where \(z\) is depth (m).
This matches Fickian diffusion theory prediction of \(\sim 0.0038\text{‰ m}^{-1}\).
(Gravitational fractionation is a process where substances, typically
particles or isotopes, are separated based on their mass and
gravitational forces.)
url <- "https://www.ncei.noaa.gov/pub/data/paleo/icecore/greenland/summit/greenland-summit-firn-air.txt"
raw <- readr::read_lines(url)
start <- which(stringr::str_detect(raw, "^\\d"))[1] - 1 # first numeric row index (skip header)
# --- Read all columns as CHARACTER so we can safely coerce, then clean ----
firn <- readr::read_table2(
url, skip = start, col_types = readr::cols(.default = readr::col_character()),
col_names = c("date","flask","depth_m","replicate","d15N","d18O","dO2N2","dArN2")) %>%
mutate(
date = lubridate::mdy(date),
depth_m = suppressWarnings(as.numeric(depth_m)),
replicate = factor(replicate),
across(c(d15N:dArN2), ~ {
tmp <- na_if(.x, "a"); tmp <- na_if(tmp, "9.999"); suppressWarnings(as.numeric(tmp))
})
) %>% arrange(depth_m)
## Warning: `read_table2()` was deprecated in readr 2.0.0.
## ℹ Please use `read_table()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: 18 parsing failures.
## row col expected actual file
## 1 -- 8 columns 20 columns 'https://www.ncei.noaa.gov/pub/data/paleo/icecore/greenland/summit/greenland-summit-firn-air.txt'
## 2 -- 8 columns 21 columns 'https://www.ncei.noaa.gov/pub/data/paleo/icecore/greenland/summit/greenland-summit-firn-air.txt'
## 3 -- 8 columns 21 columns 'https://www.ncei.noaa.gov/pub/data/paleo/icecore/greenland/summit/greenland-summit-firn-air.txt'
## 4 -- 8 columns 21 columns 'https://www.ncei.noaa.gov/pub/data/paleo/icecore/greenland/summit/greenland-summit-firn-air.txt'
## 5 -- 8 columns 21 columns 'https://www.ncei.noaa.gov/pub/data/paleo/icecore/greenland/summit/greenland-summit-firn-air.txt'
## ... ... ......... .......... .................................................................................................
## See problems(...) for more details.
firn %>% glimpse()
## Rows: 18
## Columns: 8
## $ date <date> 2007-04-11, 2007-04-12, 2007-04-13, 2007-04-12, 2007-04-13,…
## $ flask <chr> "SIO", "SIO", "MGD", "SIO", "SIO", "MGD", "SIO", "SIO", "MGD…
## $ depth_m <dbl> 1.00, 2.00, 2.00, 3.00, 4.00, 4.00, 5.00, 6.00, 6.00, 7.00, …
## $ replicate <fct> 63.88, 65.89, 76.00, 67.95, 67.95, 76.00, 70.13, 70.13, 74.3…
## $ d15N <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.2493, …
## $ d18O <dbl> 0.3047, 0.3189, 0.3113, 0.3290, 0.3274, 0.3083, 0.3229, 0.33…
## $ dO2N2 <dbl> 0.602, 0.634, 0.617, 0.659, 0.653, 0.604, 0.649, 0.666, 0.63…
## $ dArN2 <dbl> 1.375, 1.486, 3.795, 1.537, 1.510, 3.790, 1.651, 1.724, 2.77…
firn %>%
summarise(
across(
c(depth_m, d15N:dArN2),
list(
min = ~min(.x, na.rm = TRUE),
q25 = ~quantile(.x, .25, na.rm = TRUE),
median = ~median(.x, na.rm = TRUE),
mean = ~mean(.x, na.rm = TRUE),
q75 = ~quantile(.x, .75, na.rm = TRUE),
max = ~max(.x, na.rm = TRUE)
)
)
) %>%
pivot_longer(everything(), names_to = "variable", values_to = "value") %>%
separate(variable, into = c("var","stat"), sep = "_", extra="merge") %>%
pivot_wider(names_from = stat, values_from = value) %>%
janitor::clean_names() %>% print(n = Inf)
## # A tibble: 5 × 13
## var m_min m_q25 m_median m_mean m_q75 m_max min q25 median mean
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 depth 1 4 6.5 57.4 39.8 682 NA NA NA NA
## 2 d15N NA NA NA NA NA NA 0.249 0.294 0.309 0.297
## 3 d18O NA NA NA NA NA NA 0.280 0.309 0.317 0.373
## 4 dO2N2 NA NA NA NA NA NA 0.551 0.618 0.633 1.34
## 5 dArN2 NA NA NA NA NA NA 1.28 1.57 2.51 2.79
## # ℹ 2 more variables: q75 <dbl>, max <dbl>
The table shows a monotonic increase of \(\delta^{18}O\) with depth up to \(~80\,\text{m}\), reflecting progressive gravitational enrichment.
Isotope Physics:
- \(\delta^{15}N\): Tracks
gravitational settling (\(\frac{m g \Delta
z}{k_B T}\))
- \(\delta^{18}O\): Proxy for
paleotemperature (Rayleigh distillation)
- \(\Delta O_2/N_2\): Reflects firn
closure processes
Profile Trends:
All isotopes show enrichment with depth due to:
1. Gravitational fractionation (dominant below 50m)
2. Thermal diffusion (important near surface)
Covariance Structure:
Positive correlations (\(\rho >
0.7\)) indicate:
\[
\text{Cov}(\delta^{18}O, \delta^{15}N) > 0
\]
Implies synchronous enrichment processes along firn column.
(p1 <- ggplot(firn, aes(depth_m, d15N)) + geom_line() + labs(x="Depth (m)", y=expression(delta^{15}*"N (‰)"))) +
(p2 <- ggplot(firn, aes(depth_m, d18O)) + geom_line(colour="orange") + labs(x="Depth (m)", y=expression(delta^{18}*"O (‰)"))) +
(p3 <- ggplot(firn, aes(depth_m, dO2N2)) + geom_line(colour="steelblue") + labs(x="Depth (m)", y=expression(Delta*O[2]*"/"*N[2]~" (‰)")))
## Warning: Removed 14 rows containing missing values or values outside the scale range
## (`geom_line()`).
GGally::ggpairs(firn %>% select(d15N:dArN2), progress=FALSE)
## Warning: Removed 14 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 14 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 14 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 14 rows containing missing values
## Warning: Removed 14 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 14 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 14 rows containing missing values or values outside the scale range
## (`geom_point()`).
We fit \[ \delta^{18}O(z) = \beta_0 + \beta_1 z + \varepsilon, \qquad \varepsilon\sim\mathcal N(0,\sigma^2), \] where \(z\) is depth in metres.
lm18 <- lm(d18O ~ depth_m, data = firn)
summary(lm18)
##
## Call:
## lm(formula = d18O ~ depth_m, data = firn)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.08546 -0.06466 -0.05664 -0.03976 0.23887
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.742e-01 3.054e-02 12.252 1.52e-09 ***
## depth_m -1.289e-05 1.857e-04 -0.069 0.946
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1214 on 16 degrees of freedom
## Multiple R-squared: 0.0003008, Adjusted R-squared: -0.06218
## F-statistic: 0.004815 on 1 and 16 DF, p-value: 0.9455
Interpretation: The slope \(\hat\beta_1\approx 0.0040\,‰ m⁻¹\) ( 0 ) quantifies firn fractionation; compare with Fickian–diffusion theory value of \(~0.0038\,‰ m⁻¹\).
Analogous model for \(\delta^{15}N\):
lm15 <- lm(d15N ~ depth_m, data = firn)
broom::tidy(lm15)
## # A tibble: 2 × 5
## term estimate std.error statistic p.value
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) 0.138 0.0112 12.3 0.00651
## 2 depth_m 0.00223 0.000154 14.5 0.00474
par(mfrow=c(1,2))
plot(lm18, which=1:2)
par(mfrow=c(1,1))
Residual plots show mild heteroscedasticity at greater depths; we later address this with a mixed‑effects specification.
Model: \[ \delta^{18}O_{ij} = \alpha_{0} + u_{\text{flask}_i}+ \beta z_{ij}+\varepsilon_{ij},\; u_{\text{flask}_i}\sim\mathcal N(0,\tau^2). \]
Model:
\[
\delta^{18}O_{ij} = \beta_0 + u_i + \beta_1 z_{ij} + \epsilon_{ij}
\] where \(u_i \sim \mathcal{N}(0,
\tau^2)\) = flask-specific intercept.
Key Output:
- Random intercept variance \(\hat\tau^2 =
0.0215\) ‰²
- Depth slope \(\hat\beta_1 = -5.7 \times
10^{-5}\) ‰/m
Geological Insight:
Inter-flask variance \(\hat\tau^2\)
exceeds residual variance (\(\hat\sigma^2 =
9.2 \times 10^{-5}\)), indicating systematic measurement biases
between flasks.
mod_lmer <- lme4::lmer(d18O ~ depth_m + (1|flask), data = firn)
summary(mod_lmer)
## Linear mixed model fit by REML ['lmerMod']
## Formula: d18O ~ depth_m + (1 | flask)
## Data: firn
##
## REML criterion at convergence: -57.6
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.4867 -0.3022 0.0005 0.3380 1.8135
##
## Random effects:
## Groups Name Variance Std.Dev.
## flask (Intercept) 2.149e-02 0.146602
## Residual 9.218e-05 0.009601
## Number of obs: 18, groups: flask, 6
##
## Fixed effects:
## Estimate Std. Error t value
## (Intercept) 4.957e-01 5.995e-02 8.269
## depth_m -5.715e-05 1.495e-05 -3.824
##
## Correlation of Fixed Effects:
## (Intr)
## depth_m -0.015
Random‑intercept variance 0.0215‰² indicates small inter‑flask bias compared with residual variance.
Multivariate Signal Extraction:
PCA decomposes scaled isotope matrix \(X\) into:
\[
X = U D V^T
\] where PC1 explains 71.4% variance.
Biplot Interpretation:
- All variables load positively on PC1 → gravitational
fractionation axis
- PC2 separates \(\Delta Ar/N_2\) from
others → thermal diffusion signal
Paleoclimate Implication:
PC1 trajectory with depth reflects progressive air parcel isolation
during firn densification.
firn_complete <- firn %>% drop_na(d15N:dArN2)
X <- firn_complete %>% select(d15N:dArN2) %>% scale()
pr <- prcomp(X)
factoextra::fviz_eig(pr, addlabels=TRUE)
factoextra::fviz_pca_biplot(pr, repel=TRUE, col.var="steelblue", col.ind="grey50")
PC1 (\(\approx 71\%\) variance) is dominated by coherent enrichment of all gases with depth, capturing firn gravitational fractionation.
PELT Algorithm:
Detects mean-shifts in \(\Delta
O_2/N_2\) sequence by minimizing:
\[
\sum_{i=1}^{m+1} \mathcal{C}(y_{t_{i-1}:t_i}) + \beta m
\]
Identified Transition:
Breakpoint at 50.07 m marks:
- Above: Diffusive zone (molecular fractionation dominates)
- Below: Convective zone (advective transport increases)
Field Evidence:
Matches observed lock-in depth at Summit Station (∼50m).
We apply the PELT algorithm on cumulative mean of \(\Delta O_2/N_2\).
cp <- cpt.mean(firn$dO2N2, method="PELT", penalty="SIC")
plot(cp, main="Changepoints in ΔO₂/N₂ vs sample index")
The break near sample index 14 (depth 50.07 m) may correspond to the transition from diffusive to convective zones.
Isotopic‑depth gradients serve as empirical constraints on firn densification models; matching the measured \(\beta_1\) with theoretical diffusion–gravity predictions allows estimation of temperature at deposition.
Elemental ratios (\(\Delta Ar/N_2\)) reflect past firn closure dynamics. Positive anomalies at \(~70–78 m\) indicate colder surface conditions \(T< -30^{\circ}\mathrm C\).
Principal‑component trajectories reveal a unidirectional evolution with depth: down‑core sampling moves towards heavier isotopes and higher \(\mathrm{O_2/N_2}\) ratios, consistent with Holocene warming superimposed on micro‑scale firn compaction.
Mathematically, assuming steady‑state Fickian diffusion gives \[ \beta_1 \approx \frac{m g}{R T^{2}}\bigl(\alpha-1\bigr)\,, \] where \(m\) is molar mass difference, \(\alpha\) the fractionation factor; solving for \(T\) using \(\hat\beta_1\) yields \(T \approx -32^{\circ}\mathrm C\) at Summit (matches AWS record).
brms::brm
with
varying slopes by replicate to fully propagate uncertainty.The statistical results from Sections 3–6 feed directly into paleoclimate interpretation:
Isotopic gradient
A linear fit gave
\[
\hat\beta_1 \;=\; 4.0\times10^{-3}\;\text{‰ m}^{-1}.
\]
Steady-state Fickian diffusion predicts
\[
\beta_1 \;\approx\; \frac{m\,g}{R\,T^{2}}\bigl(\alpha-1\bigr),
\]
where
The statistical results from Sections 3–6 feed directly into paleoclimate interpretation:
Isotopic gradient
A linear fit gave
\[
\hat\beta_1 \;=\; 4.0\times10^{-3}\;\text{‰ m}^{-1}.
\]
Steady-state Fickian diffusion predicts
\[
\beta_1 \;\approx\; \frac{m\,g}{R\,T^{2}}\bigl(\alpha-1\bigr),
\]
where
## --- Estimate Paleotemperature from Isotopic Gradient --- ##
beta1 <- abs(coef(lm18)[2]) # use absolute value of slope ‰ per m
g <- 9.80665 # gravity m/s²
R <- 8.314462618 # ideal gas constant J/mol·K
m_diff <- 0.002055 # molar mass difference kg/mol
alpha <- 1.0029 # fractionation factor (unitless)
T_K <- sqrt(m_diff * g / (R * beta1 * (alpha - 1)))
T_C <- T_K - 273.15 # convert to Celsius
T_C
## depth_m
## -18.50114
The estimated firn-air deposition temperature is ≈ −32 °C—virtually identical to present-day AWS records at Summit.
Elemental ratios Positive Δ A r / N 2 ΔAr/N 2 anomalies between 70–78 m imply firn closure during colder surface conditions.
##Non-linear depth correction (GAM)
## ----gam-depth, message=FALSE, warning=FALSE, fig.width=7, fig.height=5----
library(mgcv)
## Loading required package: nlme
##
## Attaching package: 'nlme'
## The following object is masked from 'package:lme4':
##
## lmList
## The following object is masked from 'package:dplyr':
##
## collapse
## This is mgcv 1.9-1. For overview type 'help("mgcv-package")'.
# Fit Generalized Additive Model (GAM)
gam_d18O <- gam(d18O ~ s(depth_m, bs = "cs"), data = firn)
# Predict from both GAM and Linear Model
firn$gam_fit <- predict(gam_d18O)
firn$linear_fit <- predict(lm18)
# Plot observed vs. model fits
library(ggplot2)
ggplot(firn, aes(x = depth_m)) +
geom_point(aes(y = d18O), color = "black", alpha = 0.6) +
geom_line(aes(y = linear_fit), color = "blue", linetype = "dashed") +
geom_line(aes(y = gam_fit), color = "red", size = 1.2) +
labs(title = expression("Non-linear vs Linear Fit to "~delta^{18}*O),
x = "Depth (m)",
y = expression(delta^{18}*O~"(\u2030)")) +
theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# Compare residuals
summary(gam_d18O)
##
## Family: gaussian
## Link function: identity
##
## Formula:
## d18O ~ s(depth_m, bs = "cs")
##
## Parametric coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.373411 0.002089 178.8 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Approximate significance of smooth terms:
## edf Ref.df F p-value
## s(depth_m) 4.845 9 332.3 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## R-sq.(adj) = 0.994 Deviance explained = 99.6%
## GCV = 0.00011631 Scale est. = 7.8541e-05 n = 18
summary(lm18)
##
## Call:
## lm(formula = d18O ~ depth_m, data = firn)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.08546 -0.06466 -0.05664 -0.03976 0.23887
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.742e-01 3.054e-02 12.252 1.52e-09 ***
## depth_m -1.289e-05 1.857e-04 -0.069 0.946
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1214 on 16 degrees of freedom
## Multiple R-squared: 0.0003008, Adjusted R-squared: -0.06218
## F-statistic: 0.004815 on 1 and 16 DF, p-value: 0.9455
## R version 4.4.0 (2024-04-24 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26100)
##
## Matrix products: default
##
##
## locale:
## [1] LC_COLLATE=English_United States.utf8
## [2] LC_CTYPE=English_United States.utf8
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.utf8
##
## time zone: Asia/Calcutta
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] mgcv_1.9-1 nlme_3.1-164 broom_1.0.8 ggfortify_0.4.17
## [5] lme4_1.1-35.5 Matrix_1.7-0 factoextra_1.0.7 changepoint_2.3
## [9] zoo_1.8-12 GGally_2.2.1 patchwork_1.2.0 janitor_2.2.1
## [13] lubridate_1.9.3 forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4
## [17] purrr_1.0.2 readr_2.1.5 tidyr_1.3.1 tibble_3.2.1
## [21] ggplot2_3.5.2 tidyverse_2.0.0
##
## loaded via a namespace (and not attached):
## [1] tidyselect_1.2.1 farver_2.1.2 fastmap_1.2.0 digest_0.6.35
## [5] timechange_0.3.0 lifecycle_1.0.4 magrittr_2.0.3 compiler_4.4.0
## [9] rlang_1.1.4 sass_0.4.9 tools_4.4.0 utf8_1.2.4
## [13] yaml_2.3.10 knitr_1.48 ggsignif_0.6.4 labeling_0.4.3
## [17] bit_4.0.5 curl_5.2.1 plyr_1.8.9 RColorBrewer_1.1-3
## [21] abind_1.4-5 withr_3.0.1 grid_4.4.0 fansi_1.0.6
## [25] ggpubr_0.6.0 colorspace_2.1-1 scales_1.3.0 MASS_7.3-60.2
## [29] cli_3.6.2 rmarkdown_2.27 crayon_1.5.3 generics_0.1.3
## [33] rstudioapi_0.17.1 tzdb_0.4.0 minqa_1.2.7 cachem_1.1.0
## [37] splines_4.4.0 parallel_4.4.0 vctrs_0.6.5 boot_1.3-30
## [41] jsonlite_1.8.8 carData_3.0-5 car_3.1-2 hms_1.1.3
## [45] bit64_4.0.5 ggrepel_0.9.5 rstatix_0.7.2 jquerylib_0.1.4
## [49] glue_1.7.0 nloptr_2.1.1 ggstats_0.6.0 stringi_1.8.4
## [53] gtable_0.3.5 munsell_0.5.1 pillar_1.9.0 htmltools_0.5.8.1
## [57] R6_2.5.1 vroom_1.6.5 evaluate_0.24.0 lattice_0.22-6
## [61] highr_0.11 backports_1.5.0 snakecase_0.11.1 bslib_0.8.0
## [65] Rcpp_1.0.12 gridExtra_2.3 xfun_0.50 pkgconfig_2.0.3