::here("code", "_common.R") |>
heresource()
# Load packages
if (!requireNamespace("pacman")) install.packages("pacman")
::p_load(mice) pacman
52 Distribuzioni coniugate (2)
- calcolare la distribuzione a posteriori del caso beta-binomiale.
- Leggere il capitolo Conjugate Families del testo di Johnson et al. (2022).
52.1 Introduzione
La statistica bayesiana aggiorna ciò che credevamo prima, chiamato prior, con ciò che osserviamo ora, i dati, per produrre ciò che sappiamo dopo, la posteriori. In pratica:
- partiamo da una distribuzione a priori su un parametro, qui la media \(\mu\);
- osserviamo un campione e ne calcoliamo la verosimiglianza;
- combiniamo le due informazioni tramite il teorema di Bayes per ottenere la distribuzione a posteriori, che incorpora sia le conoscenze pregresse sia l’evidenza empirica.
L’effetto principale è che l’incertezza, misurata dalla varianza, sulla stima di \(\mu\) diminuisce: più dati abbiamo, più la distribuzione si restringe.
In questo capitolo esploriamo le famiglie coniugate (Capitolo 51), concentrandoci sul modello normale-normale. Quando sia la prior sia la verosimiglianza sono distribuzioni gaussiane, anche la distribuzione a posteriori risulta gaussiana.
52.2 Vantaggi della Scelta Gaussiana
Simmetria e Universalità: La forma a campana simmetrica approssima adeguatamente molti fenomeni psicologici, ad esempio i tempi di reazione o i punteggi QI. La simmetria facilita l’interpretazione di media e varianza come parametri centrali.
Economia Parametrica: L’incertezza è catturata da un solo parametro, \(\sigma^2\), semplificando la comunicazione dei risultati.
Consistenza con l’Inferenza Frequentista: Per grandi campioni, le stime bayesiane convergono a quelle classiche, una proprietà nota come calibrazione frequente, offrendo un ponte tra paradigmi.
Trattabilità Matematica: Le operazioni tra distribuzioni gaussiane rimangono in forma chiusa, evitando complessi calcoli numerici.
Morale: se ci aspettiamo molti dati o una posteriori unimodale e simmetrica, la distribuzione normale è un ottimo lavoro di prima approssimazione.
52.3 Inferenza con varianza nota
Supponiamo di aver misurato i tempi di reazione in millisecondi di 20 studenti durante un compito Stroop, volendo stimare il vero tempo medio \(\mu\) della popolazione. Assumiamo nota la variabilità intrinseca del compito, \(\sigma = 50\) ms.
52.3.1 I tre passi dell’Inferenza Bayesiana
Passo | Significato intuitivo | Notazione |
---|---|---|
A. Prior | Opinione preliminare su \(\mu\) | \(\mu \sim \mathcal{N}(\mu_0,\sigma_0^2)\) |
B. Verosimiglianza | Che cosa dicono i dati | \(y_i \stackrel{\text{iid}}{\sim} \mathcal{N}(\mu,\sigma^2)\) |
C. Posteriori | Opinione aggiornata | \(\mu \mid y \sim \mathcal{N}(\mu_p,\sigma_p^2)\) |
Con \(\sigma^2\) fisso la distribuzione normale è coniugata: la forma rimane invariata in ogni passaggio.
52.3.2 Distribuzione A priori
\(\mu \sim \mathcal{N}(\mu_0,\sigma_0^2)\): descrive dove crediamo sia \(\mu\) e quanta incertezza abbiamo, una varianza grande significa poca informazione.
52.3.3 Verosimiglianza
\[ p(y\mid\mu,\sigma)=\prod_{i=1}^{n}\frac{1}{\sigma\sqrt{2\pi}} \exp\!\Bigl[-\tfrac{(y_i-\mu)^2}{2\sigma^2}\Bigr]. \]
52.3.4 Teorema di Bayes
Il teorema di Bayes combina prior e verosimiglianza attraverso un prodotto ponderato:
\[ p(\mu\mid y)=\frac{p(y\mid\mu)\,p(\mu)}{p(y)} \;\; \propto\;\; \underbrace{\mathcal{N}(\mu_0,\sigma_0^2)}_{\text{prior}} \; \times \; \underbrace{\mathcal{N}(\bar y,\sigma^2/n)}_{\text{verosimiglianza}} . \]
Il prodotto di due distribuzioni gaussiane è una distribuzione gaussiana: basta aggiornare media e varianza.
52.3.5 Media a posteriori
\[ \mu_p=\frac{\tfrac{1}{\sigma_0^2}\,\mu_0 + \tfrac{n}{\sigma^2}\,\bar y} {\tfrac{1}{\sigma_0^2} + \tfrac{n}{\sigma^2}}, \qquad \bar y=\frac{1}{n}\sum_{i=1}^{n}y_i. \]
\(\mu_0\): l’idea iniziale.
\(\sigma_0^2\): la fiducia in quell’idea.
\(\bar y\): ciò che dicono i dati.
\(n/\sigma^2\): la quantità di informazione empirica, aumenta con più casi e diminuisce con misure rumorose.
Interpretazione: Il peso relativo di prior e dati dipende dalla loro credibilità:
- La prior è influente se ha alta precisione, ovvero 1/\(\sigma_0^2\) è grande, o se ci sono pochi dati, \(n\) piccolo.
- I dati sono dominanti se la prior ha bassa precisione o se c’è un ampio campione.
52.3.6 Varianza a posteriori
\[\sigma_p^2=\frac{1}{\tfrac{1}{\sigma_0^2}+\tfrac{n}{\sigma^2}}.\]
- Proprietà Chiave: \(\sigma_p^2 \le \min(\sigma_0^2, \sigma^2/n)\). L’incertezza diminuisce monotonicamente all’aumentare di \(n\).
Esempio 52.1 Consideriamo l’esempio dei tempi di reazione nell’effetto Stroop. La prior e i dati osservati sono i seguenti:
Simbolo | Valore |
---|---|
\(\mu_0\) | 500 ms |
\(\sigma_0\) | 100 ms |
\(\sigma\) | 50 ms |
\(n\) | 20 |
\(\bar y\) | 480 ms |
Pesi
\[ \frac{1}{\sigma_0^{2}}=\frac{1}{100^{2}}=0.0001,\quad \frac{n}{\sigma^{2}}=\frac{20}{50^{2}}=0.008 \]
Media a posteriori
\[ \mu_p=\frac{0.0001\cdot500 + 0.008\cdot480}{0.0081}\approx 480.2\text{ ms} \]
Varianza a posteriori
\[ \sigma_p^{2}=\frac{1}{0.0081}\approx 123 \implies \sigma_p\approx 11\text{ ms} \]
Risultato: da circa \(\mu\approx500\pm100\) ms a circa \(\mu\approx480\pm11\) ms. Un salto enorme di precisione dopo sole 20 osservazioni.
- Bayes è un dialogo fra ipotesi e dati.
- Con varianza nota i conti sono lineari e si fanno a mano.
- L’incertezza può solo scendere dopo aver visto i dati.
- Con pochi dati o molto rumore la prior pesa tanto; con molti dati precisi quasi scompare.
- Lo stesso schema si applica a moltissimi problemi di psicologia sperimentale come tempi di reazione, punteggi o ampiezze EEG.
# ---- Parametri dell'esempio -------------------------------------------
<- 500 # Media a priori (intuizione iniziale)
mu0 <- 100 # Deviazione standard a priori (quanto siamo incerti)
sigma0 <- 50 # Deviazione standard nota (errore di misura)
sigma <- 20 # Dimensione del campione
n <- 480 # Media campionaria osservata
ybar
# ---- Calcolo dei parametri a posteriori -------------------------------
<- 1 / (1 / sigma0^2 + n / sigma^2) # Varianza a posteriori
sigma_p2 <- sqrt(sigma_p2) # Deviazione standard a posteriori
sigma_p <- (mu0 / sigma0^2 + n * ybar / sigma^2) /
mu_p 1 / sigma0^2 + n / sigma^2) # Media a posteriori
(
# ---- Griglia di valori per il parametro mu -----------------------------
<- seq(400, 600, length.out = 1000)
mu_grid
# ---- Calcolo delle densità delle tre curve -----------------------------
<- dnorm(mu_grid, mean = mu0, sd = sigma0) # Densità a priori
prior_dens <- dnorm(mu_grid, mean = mu_p, sd = sigma_p) # Densità a posteriori
post_dens
# Verosimiglianza (scalata per confrontabilità grafica)
<- dnorm(mu_grid, mean = ybar, sd = sigma / sqrt(n))
lik_prop <- lik_prop * max(prior_dens) / max(lik_prop)
lik_dens
# ---- Preparazione dati in formato "lungo" per ggplot2 ------------------
<- tibble(
df mu = mu_grid,
Prior = prior_dens,
Likelihood = lik_dens,
Posterior = post_dens
)
<- pivot_longer(df, -mu, names_to = "Curve", values_to = "Density")
df_long
# ---- Grafico delle distribuzioni ---------------------------------------
ggplot(df_long, aes(x = mu, y = Density, colour = Curve)) +
geom_line(linewidth = 1) +
labs(
x = expression(mu),
y = "Densità (unità arbitrarie)",
title = "Distribuzioni a priori, verosimiglianza (riscalata)\ne distribuzione a posteriori"
+
) theme(legend.title = element_blank())
Esempio 52.2 I test standard di QI sono progettati per misurare l’intelligenza con una media di 100 e una deviazione standard di 15. Tuttavia, si dice anche che questi test presentino bias culturali che favoriscono alcuni gruppi rispetto ad altri. Un’ulteriore complicazione si verifica quando i punteggi di QI vengono aggregati a livello nazionale, poiché le caratteristiche interne ai paesi vengono mascherate. Questo esempio analizza i dati di QI raccolti a livello internazionale (Lynn e Vanhanen, 2001) per 80 paesi da fonti nazionali pubblicate e discussi da Gill (2015). L’idea chiave nella descrizione della distribuzione a posteriori è se le differenze tra le nazioni alterano la parametrizzazione prevista.
I dati di Lynn e Vanhanen (2001) sono forniti di seguito:
Paese | IQ | Paese | IQ | Paese | IQ | Paese | IQ |
---|---|---|---|---|---|---|---|
Argentina | 96 | Australia | 98 | Austria | 102 | Barbados | 78 |
Belgium | 100 | Brazil | 87 | Bulgaria | 93 | Canada | 97 |
China | 100 | Congo (Br.) | 73 | Congo (Zr.) | 65 | Croatia | 90 |
Cuba | 85 | Czech Repub. | 97 | Denmark | 98 | Ecuador | 80 |
Egypt | 83 | Eq. Guinea | 59 | Ethiopia | 63 | Fiji | 84 |
Finland | 97 | France | 98 | Germany | 102 | Ghana | 71 |
Greece | 92 | Guatemala | 79 | Guinea | 66 | Hong Kong | 107 |
Hungary | 99 | India | 81 | Indonesia | 89 | Iran | 84 |
Iraq | 87 | Ireland | 93 | Israel | 94 | Italy | 102 |
Jamaica | 72 | Japan | 105 | Kenya | 72 | Korea (S.) | 106 |
Lebanon | 86 | Malaysia | 92 | Marshall I. | 84 | Mexico | 87 |
Morocco | 85 | Nepal | 78 | Netherlands | 102 | New Zealand | 100 |
Nigeria | 67 | Norway | 98 | Peru | 90 | Philippines | 86 |
Poland | 99 | Portugal | 95 | Puerto Rico | 84 | Qatar | 78 |
Romania | 94 | Russia | 96 | Samoa | 87 | Sierra Leone | 64 |
Singapore | 103 | Slovakia | 96 | Slovenia | 95 | South Africa | 72 |
Spain | 97 | Sudan | 72 | Suriname | 89 | Sweden | 101 |
Switzerland | 101 | Taiwan | 104 | Tanzania | 72 | Thailand | 91 |
Tonga | 87 | Turkey | 90 | Uganda | 73 | U.K. | 100 |
U.S. | 98 | Uruguay | 96 | Zambia | 77 | Zimbabwe | 66 |
Implementiamo le informazioni necessarie in R.
# Dati IQ delle 80 nazioni
<- c(
iq 96, 100, 100, 85, 83, 97, 92, 99, 87, 72, 86, 85, 67, 99, 94, 103, 97, 101,
87, 98, 87, 73, 97, 59, 98, 79, 81, 93, 105, 92, 78, 98, 95, 96, 72, 104,
90, 96, 98, 102, 78, 90, 63, 84, 84, 107, 86, 102, 106, 94, 102, 72, 101,
89, 72, 101, 91, 100, 100, 66, 107, 86, 78, 84, 78, 64, 72, 101, 91, 100,
67, 86
)
# Numero di osservazioni
<- length(iq)
n
# Media campionaria
<- mean(iq)
y_bar
# Deviazione standard nota
<- 15
sigma
# Parametri a priori
<- 100
mu_0 <- 15 sigma_0
Calcoliamo la media a posteriori con la formula discussa in precedenza
\[ \mu_p = \frac{\frac{1}{\sigma_0^2}\mu_0 + \frac{n}{\sigma^2}\bar{y}}{\frac {1}{\sigma_0^2} + \frac{n}{\sigma^2}} \]
dove:
- \(\mu_0\) è la media a priori
- \(\sigma_0\) è la deviazione standard a priori
- \(n\) è il numero di osservazioni
- \(\sigma\) è la deviazione standard delle osservazioni (nota)
- \(\bar{y}\) è la media campionaria
<- ((1 / sigma_0^2) * mu_0 + (n / sigma^2) * y_bar) /
mu_p 1 / sigma_0^2) + (n / sigma^2))
((print(paste("Media a posteriori (mu_p):", round(mu_p, 2)))
#> [1] "Media a posteriori (mu_p): 89.36"
Calcoliamo la varianza a posteriori
\[ \sigma_p^2 = \frac{1}{\frac {1}{\sigma_0^2}+ \frac{n}{\sigma^2}} \]
<- 1 / ((1 / sigma_0^2) + (n / sigma^2))
sigma_p_sq <- sqrt(sigma_p_sq)
sigma_p print(paste("Varianza a posteriori (sigma_p_sq):", round(sigma_p_sq, 2)))
#> [1] "Varianza a posteriori (sigma_p_sq): 3.08"
Generiamo una rappresentazione grafica della distribuzione a posteriori della media del IQ sulla base dei dati osservati, avendo assunto mu_0
= 100 e sigma_0
= 15 per la distribuzione a priori.
# Definizione dei valori sull'asse x
<- seq(mu_p - 4 * sigma_p, mu_p + 4 * sigma_p, length.out = 1000)
x
# Calcolo della densità di probabilità
<- dnorm(x, mean = mu_p, sd = sigma_p)
pdf
# Creazione del grafico
ggplot(data.frame(x = x, pdf = pdf), aes(x = x, y = pdf)) +
geom_line(color = "blue", linewidth = 1) +
geom_area(aes(fill = "Posterior"), alpha = 0.2) +
scale_fill_manual(values = c("blue")) +
labs(
x = "Media del Quoziente di Intelligenza",
y = "Densità di probabilità"
+
) theme(legend.position = "none")
L’analisi condotta mediante un modello bayesiano basato sulla distribuzione normale ha prodotto un risultato interessante: la media stimata della distribuzione a posteriori del QI si attesta a 89.36, un valore sensibilmente inferiore ai 100 punti previsti come media standard.
Tuttavia, per un’interpretazione completa di questo dato, è fondamentale adottare un approccio critico che consideri alcuni aspetti cruciali:
- La media a posteriori è ottenuta aggregando i dati QI di 80 nazioni diverse. Questo processo può innescare un effetto di aggregazione, dove la media “smussata” risultante non rispecchia accuratamente la distribuzione del QI a livello individuale in ogni singola nazione. Di conseguenza, le differenze tra le nazioni in termini di QI medio e variabilità potrebbero essere mascherate da questa media aggregata.
- È importante sottolineare che la media a posteriori viene calcolata utilizzando dati non ponderati per ogni nazione. Ciò significa che nazioni con popolazioni più piccole, anche se con punteggi QI mediamente più alti o più bassi, hanno lo stesso impatto sulla media aggregata rispetto a nazioni con popolazioni più grandi. Questo aspetto potrebbe ulteriormente distorcere la rappresentazione della vera distribuzione globale del QI.
- La deviazione osservata dalla media standard di 100 potrebbe non riflettere esclusivamente differenze nell’intelligenza media tra le nazioni, ma anche differenze nei contesti sanitari, sociologici e politici in cui i test sono stati somministrati. Fattori quali l’accesso all’istruzione, la qualità della nutrizione e l’esposizione a stimoli cognitivi possono influenzare i punteggi QI ottenuti e contribuire alla variabilità osservata tra le nazioni.
- Inoltre, è fondamentale considerare la possibilità di un bias culturale intrinseco allo strumento stesso. I test del QI sono stati originariamente progettati per un contesto specifico (paese industrializzato di lingua inglese) e potrebbero non essere adatti o culturalmente sensibili a contesti differenti. Questo potrebbe portare a una sottostima dei punteggi QI in alcune nazioni e influenzare la media a posteriori aggregata.
Questi risultati evidenziano l’importanza di un’attenta considerazione dei fattori metodologici quando si interpretano dati di test del QI a livello trans-culturale. L’effetto di aggregazione, l’utilizzo di medie non ponderate, le differenze nei contesti e il potenziale bias culturale richiedono un’analisi più approfondita che consideri questi fattori e utilizzi metodi statistici più sofisticati per ottenere una comprensione più completa delle differenze nel QI tra le nazioni.
52.4 Riflessioni Conclusive
In questo capitolo, abbiamo approfondito il meccanismo dell’aggiornamento bayesiano attraverso l’implementazione del modello normale-normale. Il processo inizia definendo una distribuzione a priori per \(\mu\), specificata da una media \(\mu_0\) e una varianza \(\sigma_0^2\). Dopo l’acquisizione di nuovi dati, ipotizzando che seguano una distribuzione Normale con media campionaria \(\bar{y}\) e varianza nota \(\sigma^2\), implementiamo il teorema normale-normale per derivare la distribuzione a posteriori del parametro.
La media della distribuzione a posteriori, denotata come \(\mu_{\text{post}}\), si configura come una media ponderata tra la media a priori \(\mu_0\) e la media campionaria \(\bar{y}\), dove il peso assegnato a ciascuna media è determinato dalle rispettive varianze \(\sigma_0^2\) e \(\sigma^2\) della distribuzione a priori e dei dati osservati. Analogamente, la varianza a posteriori \(\sigma_{\text{post}}^2\) è determinata utilizzando un’espressione che incorpora entrambe le varianze.
In sintesi, l’adozione del modello normale-normale in un contesto bayesiano facilita il calcolo delle distribuzioni a posteriori, grazie alla scelta di una distribuzione a priori Normale che mantiene la proprietà di coniugatezza, semplificando così l’intero processo analitico.
Esercizi
Riprendi i dati della SWLS che sono stati utilizzati nell’esercizio del Capitolo 50. Trova la media e la deviazione standard della distribuzione a posteriori usando il metodo delle distribuzioni coniugate. Confronta i risultati con quelli ottenuti con il metodo basato su griglia.
Consegna: Carica il file .qmd, convertito in PDF, su Moodle.
Per risolvere questo esercizio con il metodo delle distribuzioni coniugate, assumiamo che i dati provengano da una distribuzione normale con deviazione standard nota e media da stimare. Nel caso di una verosimiglianza gaussiana con prior gaussiano, la distribuzione a posteriori sarà ancora una distribuzione normale. Questo approccio è analitico e ci permette di ottenere la media e la deviazione standard della distribuzione a posteriori senza dover ricorrere a metodi numerici come la discretizzazione della griglia.
Passaggi per il calcolo della distribuzione a posteriori
- Definiamo i dati osservati:
- La media campionaria: \(\bar{x}\)
- La deviazione standard nota dei dati: \(\sigma\)
- Il numero di osservazioni: \(n\)
- Scegliamo un prior gaussiano molto diffuso:
- Media a priori: \(\mu_0\)
- Deviazione standard a priori molto grande: \(\sigma_0\)
- Calcoliamo la media e la varianza della distribuzione a posteriori:
La media a posteriori è:
\[ \mu_{\text{post}} = \frac{\sigma^2_0 \bar{x} + \sigma^2 n \mu_0}{\sigma^2_0 + \sigma^2 n} \]
La varianza a posteriori è:
\[ \sigma^2_{\text{post}} = \frac{\sigma^2_0 \sigma^2}{\sigma^2_0 + \sigma^2 n} \]
Implementazione in R
# Caricamento librerie necessarie
library(dplyr)
library(tibble)
# Dati SWLS
<- data.frame(
swls_data soddisfazione = c(4.2, 5.1, 4.7, 4.3, 5.5, 4.9, 4.8, 5.0, 4.6, 4.4)
)
# Parametri comuni per entrambi i metodi
<- sd(swls_data$soddisfazione) # Usando la deviazione standard campionaria
sigma_conosciuta <- nrow(swls_data)
n <- mean(swls_data$soddisfazione)
mean_x
cat("Deviazione standard campionaria:", sigma_conosciuta, "\n")
cat("Media campionaria:", mean_x, "\n")
# ---- Metodo 1: Griglia ----
# Definizione della griglia più fine e centrata intorno alla media campionaria
<- seq(mean_x - 3*sigma_conosciuta/sqrt(n),
mu_griglia + 3*sigma_conosciuta/sqrt(n),
mean_x length.out = 1000)
# Calcolo della verosimiglianza
<- numeric(length(mu_griglia))
log_likelihood for (i in seq_along(mu_griglia)) {
# Utilizzo della log-likelihood per evitare problemi numerici
<- sum(dnorm(swls_data$soddisfazione,
log_likelihood[i] mean = mu_griglia[i],
sd = sigma_conosciuta,
log = TRUE))
}
# Prior uniforme (in scala logaritmica)
<- rep(0, length(mu_griglia))
log_prior
# Calcolo della posteriori
<- log_likelihood + log_prior
log_posterior <- exp(log_posterior - max(log_posterior))
posterior <- posterior / sum(posterior)
posterior
# Campionamento e calcolo statistiche
<- sample(mu_griglia, size = 10000, replace = TRUE, prob = posterior)
samples_grid <- mean(samples_grid)
mean_post_grid <- sd(samples_grid)
sd_post_grid <- quantile(samples_grid, c(0.03, 0.97))
ci_grid
# ---- Metodo 2: Soluzione analitica ----
# Prior poco informativo ma non improprio
<- mean_x
mu_prior <- 10
sigma_prior
# Calcolo posteriori
<- (sigma_prior^2 * mean_x + sigma_conosciuta^2 * mu_prior/n) /
mu_post_analytic ^2 + sigma_conosciuta^2/n)
(sigma_prior<- sqrt((sigma_prior^2 * sigma_conosciuta^2/n) /
sigma_post_analytic ^2 + sigma_conosciuta^2/n))
(sigma_prior
# Confronto risultati
<- tibble(
results Metodo = c("Griglia", "Analitico"),
`Media Posteriori` = c(mean_post_grid, mu_post_analytic),
`Dev. Std. Posteriori` = c(sd_post_grid, sigma_post_analytic)
) results
Interpretazione dei risultati
- La media a posteriori rappresenta la miglior stima aggiornata della media della popolazione dopo aver osservato i dati.
- La deviazione standard a posteriori ci dice quanto è incerta la nostra stima della media dopo aver integrato i dati e il prior.
Siccome abbiamo scelto un prior molto diffuso (\(\sigma_0 = 10\)), il risultato ottenuto è molto vicino a quello ottenuto con il metodo della griglia, dove il prior uniforme aveva un impatto minimo sulla distribuzione a posteriori.
Questa implementazione analitica permette di ottenere il risultato in modo efficiente senza necessità di metodi numerici approssimati.
Informazioni sull’Ambiente di Sviluppo
sessionInfo()
#> R version 4.5.0 (2025-04-11)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Sequoia 15.4.1
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
#>
#> locale:
#> [1] C/UTF-8/C/C/C/C
#>
#> time zone: Europe/Rome
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] mice_3.17.0 thematic_0.1.6 MetBrewer_0.2.0 ggokabeito_0.1.0
#> [5] see_0.11.0 gridExtra_2.3 patchwork_1.3.0 bayesplot_1.12.0
#> [9] psych_2.5.3 scales_1.3.0 markdown_2.0 knitr_1.50
#> [13] lubridate_1.9.4 forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4
#> [17] purrr_1.0.4 readr_2.1.5 tidyr_1.3.1 tibble_3.2.1
#> [21] ggplot2_3.5.2 tidyverse_2.0.0 rio_1.2.3 here_1.0.1
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.6 shape_1.4.6.1 xfun_0.52 htmlwidgets_1.6.4
#> [5] lattice_0.22-7 tzdb_0.5.0 Rdpack_2.6.4 vctrs_0.6.5
#> [9] tools_4.5.0 generics_0.1.3 parallel_4.5.0 pan_1.9
#> [13] pacman_0.5.1 jomo_2.7-6 pkgconfig_2.0.3 Matrix_1.7-3
#> [17] lifecycle_1.0.4 compiler_4.5.0 farver_2.1.2 munsell_0.5.1
#> [21] mnormt_2.1.1 codetools_0.2-20 htmltools_0.5.8.1 glmnet_4.1-8
#> [25] nloptr_2.2.1 pillar_1.10.2 MASS_7.3-65 reformulas_0.4.0
#> [29] iterators_1.0.14 rpart_4.1.24 boot_1.3-31 mitml_0.4-5
#> [33] foreach_1.5.2 nlme_3.1-168 tidyselect_1.2.1 digest_0.6.37
#> [37] stringi_1.8.7 labeling_0.4.3 splines_4.5.0 rprojroot_2.0.4
#> [41] fastmap_1.2.0 grid_4.5.0 colorspace_2.1-1 cli_3.6.4
#> [45] magrittr_2.0.3 survival_3.8-3 broom_1.0.8 withr_3.0.2
#> [49] backports_1.5.0 timechange_0.3.0 rmarkdown_2.29 nnet_7.3-20
#> [53] lme4_1.1-37 hms_1.1.3 evaluate_1.0.3 rbibutils_2.3
#> [57] rlang_1.1.6 Rcpp_1.0.14 glue_1.8.0 minqa_1.2.8
#> [61] rstudioapi_0.17.1 jsonlite_2.0.0 R6_2.6.1