Skip to content

Commit 9bd301e

Browse files
committed
feat(v0.4.0): add new experimental designs, assumption audits, model comparison, diagnostic recommender, and publication figures
1 parent 06d0b9b commit 9bd301e

26 files changed

Lines changed: 1765 additions & 546 deletions

DESCRIPTION

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
Package: easyModels
22
Type: Package
3-
Title: Herramientas Automatizadas para Modelos Lineales, Mixtos y Graficos Cientificos
4-
Version: 0.3.0
3+
Title: Herramientas Automatizadas para Modelos Lineales, Mixtos y Gráficos Científicos
4+
Version: 0.4.0
55
Authors@R:
66
person(
77
given = "Paul Alexander",
88
family = "Lopez Pena",
99
email = "paullopezpena@gmail.com",
1010
role = c("aut", "cre")
1111
)
12-
Description: Paquete disenado para automatizar el analisis de disenos experimentales
13-
biologicos, incluyendo la jerarquia de modelos lineales (lm, aov), GLM con amplia
14-
gama de distribuciones (Gaussian, Binomial, Poisson, Gamma, Beta, Tweedie,
15-
zero-infladas, ordinal, multinomial), modelos lineales mixtos (LMM) y GLMM con
16-
soporte de glmmTMB y DHARMa para distribuciones avanzadas, analisis post-hoc con
17-
emmeans y exportacion de graficos de predichos listos para publicacion.
18-
Implementa una arquitectura S3 unificada bajo la clase easy_model con metodos
19-
print, summary y plot consistentes.
12+
Description: Paquete de R disenado para automatizar el analisis estadistico y bioestadistico
13+
en ciencias biologicas, agronomia y medicina experimental. Incluye jerarquia completa
14+
de modelos lineales (LM), GLM con 17 familias (Gaussiana, Binomial, Poisson, Gamma,
15+
Beta, Tweedie, Zero-infladas ZIP/ZINB, Ordinal, Multinomial), modelos lineales mixtos (LMM)
16+
y GLMM (16 distribuciones via glmmTMB y lme4). Ofrece wrappers para disenos experimentales
17+
clasicos (RCBD, Split-Plot, Cuadrado Latino, Strip-Plot, Medidas Repetidas), auditoria
18+
automatizada de supuestos (normalidad, homocedasticidad, VIF, Cook's D), seleccion de modelos
19+
con criterios de informacion (AIC, delta-AIC, pesos de Akaike), asistente bioestadistico
20+
de transformacion de datos, post-hoc con emmeans y letras Tukey (CLD), y generacion de graficos
21+
de predichos (barras, puntos, lineas) e interacciones listos para publicacion cientifica.
22+
Arquitectura S3 unificada bajo la clase easy_model.
2023
License: MIT + file LICENSE
2124
URL: https://github.com/PALP31/easyModels
2225
BugReports: https://github.com/PALP31/easyModels/issues
@@ -37,15 +40,16 @@ Imports:
3740
cli,
3841
insight,
3942
performance,
40-
car
43+
car,
44+
knitr
4145
Suggests:
4246
glmmTMB,
4347
betareg,
4448
statmod,
4549
pscl,
4650
ordinal,
4751
nnet,
48-
knitr,
52+
patchwork,
4953
rmarkdown,
5054
testthat (>= 3.0.0)
5155
VignetteBuilder: knitr

NAMESPACE

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,35 @@ S3method(summary,easy_model)
77
export(analizar_bloques_azar)
88
export(analizar_glm)
99
export(analizar_glmm)
10+
export(analizar_latino)
1011
export(analizar_lm)
1112
export(analizar_lmm)
13+
export(analizar_medidas_repetidas)
1214
export(analizar_odds_ratio)
1315
export(analizar_parcelas_divididas)
16+
export(analizar_strip_plot)
17+
export(comparar_modelos)
1418
export(evaluar_modelo)
19+
export(exportar_tabla_anova)
20+
export(exportar_tabla_posthoc)
21+
export(graficar_interaccion)
1522
export(graficar_posthoc)
1623
export(graficar_predichos)
1724
export(obtener_emmeans)
1825
export(obtener_posthoc)
26+
export(sugerir_modelo)
27+
export(verificar_supuestos)
1928
importFrom(DHARMa,simulateResiduals)
2029
importFrom(DHARMa,testDispersion)
2130
importFrom(DHARMa,testZeroInflation)
31+
importFrom(MASS,boxcox)
2232
importFrom(MASS,glm.nb)
2333
importFrom(MASS,polr)
2434
importFrom(car,Anova)
35+
importFrom(car,durbinWatsonTest)
2536
importFrom(cli,boxx)
2637
importFrom(cli,cli_abort)
38+
importFrom(cli,cli_alert_danger)
2739
importFrom(cli,cli_alert_info)
2840
importFrom(cli,cli_alert_success)
2941
importFrom(cli,cli_alert_warning)
@@ -35,14 +47,23 @@ importFrom(cli,cli_warn)
3547
importFrom(emmeans,contrast)
3648
importFrom(emmeans,emmeans)
3749
importFrom(ggplot2,aes)
50+
importFrom(ggplot2,element_rect)
3851
importFrom(ggplot2,element_text)
52+
importFrom(ggplot2,geom_col)
3953
importFrom(ggplot2,geom_errorbar)
4054
importFrom(ggplot2,geom_line)
4155
importFrom(ggplot2,geom_point)
4256
importFrom(ggplot2,geom_ribbon)
4357
importFrom(ggplot2,geom_text)
4458
importFrom(ggplot2,ggplot)
4559
importFrom(ggplot2,labs)
60+
importFrom(ggplot2,position_dodge)
61+
importFrom(ggplot2,scale_color_brewer)
62+
importFrom(ggplot2,scale_color_manual)
63+
importFrom(ggplot2,scale_color_viridis_d)
64+
importFrom(ggplot2,scale_fill_brewer)
65+
importFrom(ggplot2,scale_fill_manual)
66+
importFrom(ggplot2,scale_fill_viridis_d)
4667
importFrom(ggplot2,theme)
4768
importFrom(ggplot2,theme_classic)
4869
importFrom(graphics,abline)
@@ -51,10 +72,14 @@ importFrom(graphics,plot)
5172
importFrom(insight,find_formula)
5273
importFrom(insight,find_response)
5374
importFrom(insight,model_info)
75+
importFrom(knitr,kable)
5476
importFrom(lme4,glmer)
5577
importFrom(lme4,glmer.nb)
5678
importFrom(lme4,lmer)
5779
importFrom(multcomp,cld)
80+
importFrom(performance,check_collinearity)
81+
importFrom(performance,check_heteroscedasticity)
82+
importFrom(performance,check_outliers)
5883
importFrom(performance,check_overdispersion)
5984
importFrom(performance,check_singularity)
6085
importFrom(performance,icc)
@@ -73,12 +98,18 @@ importFrom(stats,gaussian)
7398
importFrom(stats,glm)
7499
importFrom(stats,inverse.gaussian)
75100
importFrom(stats,lm)
101+
importFrom(stats,logLik)
76102
importFrom(stats,model.frame)
103+
importFrom(stats,na.omit)
77104
importFrom(stats,poisson)
78105
importFrom(stats,qnorm)
79106
importFrom(stats,qqline)
80107
importFrom(stats,qqnorm)
108+
importFrom(stats,quantile)
81109
importFrom(stats,quasibinomial)
82110
importFrom(stats,quasipoisson)
83111
importFrom(stats,residuals)
112+
importFrom(stats,sd)
113+
importFrom(stats,shapiro.test)
114+
importFrom(stats,var)
84115
importFrom(stats,vcov)

R/comparar_modelos.R

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#' Comparar múltiples modelos estadísticos (Selección de Modelos)
2+
#'
3+
#' Esta función compara múltiples modelos estadísticos (\code{easy_model}, \code{lm}, \code{glm}, \code{lmer}, \code{glmmTMB})
4+
#' calculando criterios de información de Akaike (AIC, BIC), log-verosimilitud (LogLik),
5+
#' diferencias delta-AIC (\eqn{\Delta AIC}), pesos de Akaike (\eqn{w_i}) y coeficientes de determinación (\eqn{R^2}).
6+
#'
7+
#' @param ... Uno o más modelos ajustados (de clase \code{easy_model} o nativos), o una lista de modelos.
8+
#' @param nombres Vector opcional de caracteres con los nombres descriptivos para cada modelo.
9+
#' @param criterio Criterio principal de ordenamiento. Opciones: \code{"AIC"} (por defecto), \code{"BIC"} o \code{"R2"}.
10+
#'
11+
#' @return Un \code{data.frame} de clase \code{c("easy_comparacion", "data.frame")} ordenado según el mejor ajuste.
12+
#' @export
13+
#'
14+
#' @importFrom stats AIC BIC logLik
15+
#' @importFrom performance r2
16+
#' @importFrom cli cli_h1 cli_alert_success cli_alert_info boxx
17+
#'
18+
#' @examples
19+
#' \dontrun{
20+
#' m1 <- analizar_lm(iris, Sepal.Length ~ Species, diagnosticos = FALSE)
21+
#' m2 <- analizar_lm(iris, Sepal.Length ~ Species + Sepal.Width, diagnosticos = FALSE)
22+
#' m3 <- analizar_lm(iris, Sepal.Length ~ Species * Sepal.Width, diagnosticos = FALSE)
23+
#' comparar_modelos(m1, m2, m3, nombres = c("Simple", "Aditivo", "Interaccion"))
24+
#' }
25+
comparar_modelos <- function(..., nombres = NULL, criterio = c("AIC", "BIC", "R2")) {
26+
criterio <- match.arg(criterio)
27+
28+
# Recoger modelos
29+
lista_mod <- list(...)
30+
if (length(lista_mod) == 1 && is.list(lista_mod[[1]]) && !inherits(lista_mod[[1]], c("easy_model", "lm", "merMod", "glmmTMB"))) {
31+
lista_mod <- lista_mod[[1]]
32+
}
33+
34+
k <- length(lista_mod)
35+
if (k < 2) {
36+
stop("Debe proporcionar al menos 2 modelos para realizar la comparacion.", call. = FALSE)
37+
}
38+
39+
if (is.null(nombres)) {
40+
llamadas <- as.character(match.call(expand.dots = FALSE)$...)
41+
if (length(llamadas) == k) {
42+
nombres <- llamadas
43+
} else {
44+
nombres <- paste0("Modelo_", seq_len(k))
45+
}
46+
}
47+
48+
tab_res <- data.frame(
49+
Modelo = nombres,
50+
Tipo = character(k),
51+
K = integer(k),
52+
LogLik = numeric(k),
53+
AIC = numeric(k),
54+
delta_AIC = numeric(k),
55+
Peso_AIC = numeric(k),
56+
BIC = numeric(k),
57+
R2_Marginal = numeric(k),
58+
R2_Condicional = numeric(k),
59+
stringsAsFactors = FALSE
60+
)
61+
62+
for (i in seq_len(k)) {
63+
obj <- lista_mod[[i]]
64+
m_nat <- extraer_modelo(obj)
65+
66+
# Tipo de modelo
67+
tipo <- if (inherits(obj, "easy_model")) obj$tipo_modelo else class(m_nat)[1]
68+
tab_res$Tipo[i] <- tipo
69+
70+
# Parametros y LogLik
71+
ll <- tryCatch(as.numeric(stats::logLik(m_nat)), error = function(e) NA)
72+
df_p <- tryCatch(attr(stats::logLik(m_nat), "df"), error = function(e) NA)
73+
tab_res$LogLik[i] <- if (!is.na(ll)) round(ll, 2) else NA
74+
tab_res$K[i] <- if (!is.na(df_p)) as.integer(df_p) else NA
75+
76+
# AIC y BIC
77+
aic_val <- tryCatch(as.numeric(stats::AIC(m_nat)), error = function(e) NA)
78+
bic_val <- tryCatch(as.numeric(stats::BIC(m_nat)), error = function(e) NA)
79+
tab_res$AIC[i] <- if (!is.na(aic_val)) round(aic_val, 2) else NA
80+
tab_res$BIC[i] <- if (!is.na(bic_val)) round(bic_val, 2) else NA
81+
82+
# R2
83+
r2_val <- tryCatch(suppressWarnings(performance::r2(m_nat)), error = function(e) NULL)
84+
r2_cond <- .safe_get(r2_val, "R2_conditional")
85+
r2_marg <- .safe_get(r2_val, "R2_marginal")
86+
r2_plain <- .safe_get(r2_val, "R2")
87+
88+
if (!is.na(r2_cond)) {
89+
tab_res$R2_Condicional[i] <- round(r2_cond, 3)
90+
tab_res$R2_Marginal[i] <- round(r2_marg, 3)
91+
} else if (!is.na(r2_plain)) {
92+
tab_res$R2_Marginal[i] <- round(r2_plain, 3)
93+
tab_res$R2_Condicional[i] <- NA
94+
} else {
95+
tab_res$R2_Marginal[i] <- NA
96+
tab_res$R2_Condicional[i] <- NA
97+
}
98+
}
99+
100+
# Calcular Delta AIC y Pesos de Akaike
101+
min_aic <- min(tab_res$AIC, na.rm = TRUE)
102+
tab_res$delta_AIC <- round(tab_res$AIC - min_aic, 2)
103+
104+
raw_weights <- exp(-0.5 * tab_res$delta_AIC)
105+
tab_res$Peso_AIC <- round(raw_weights / sum(raw_weights, na.rm = TRUE), 3)
106+
107+
# Ordenar según criterio
108+
if (criterio == "AIC") {
109+
tab_res <- tab_res[order(tab_res$AIC), ]
110+
} else if (criterio == "BIC") {
111+
tab_res <- tab_res[order(tab_res$BIC), ]
112+
} else if (criterio == "R2") {
113+
tab_res <- tab_res[order(tab_res$R2_Marginal, decreasing = TRUE), ]
114+
}
115+
rownames(tab_res) <- NULL
116+
117+
# Reporte en CLI
118+
cli::cli_h1("Tabla de Comparación y Selección de Modelos (easyModels)")
119+
mejor_modelo <- tab_res$Modelo[1]
120+
cli::cli_alert_success("Mejor modelo según {criterio}: {.strong {mejor_modelo}} (AIC = {tab_res$AIC[1]}, \u0394AIC = 0.00, Peso = {tab_res$Peso_AIC[1]})")
121+
cat("\n")
122+
print(tab_res)
123+
cat("\n")
124+
125+
class(tab_res) <- c("easy_comparacion", "data.frame")
126+
invisible(tab_res)
127+
}

0 commit comments

Comments
 (0)