4. Ancova

ANCOVA

library(tidyverse)
Warning: package 'ggplot2' was built under R version 4.3.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggpubr)
library(rstatix)

Attaching package: 'rstatix'

The following object is masked from 'package:stats':

    filter
library(broom)
Warning: package 'broom' was built under R version 4.3.3
library(tuneR)
Warning: package 'tuneR' was built under R version 4.3.3
library(readxl)
library(tidyverse)
library(egg)
Loading required package: gridExtra

Attaching package: 'gridExtra'

The following object is masked from 'package:dplyr':

    combine


Attaching package: 'egg'

The following object is masked from 'package:ggpubr':

    ggarrange
library(tidyverse)
library(ggplot2)
library(ggpmisc)
Warning: package 'ggpmisc' was built under R version 4.3.3
Loading required package: ggpp
Warning: package 'ggpp' was built under R version 4.3.3
Registered S3 methods overwritten by 'ggpp':
  method                  from   
  heightDetails.titleGrob ggplot2
  widthDetails.titleGrob  ggplot2

Attaching package: 'ggpp'

The following objects are masked from 'package:ggpubr':

    as_npc, as_npcx, as_npcy

The following object is masked from 'package:ggplot2':

    annotate

Registered S3 method overwritten by 'ggpmisc':
  method                  from   
  as.character.polynomial polynom
library(broom)
library(ggplot2)
library(patchwork)
library(egg)
library(ggpubr)
library(readxl)
library(tidyverse)
library(egg)
library(tidyverse)


dat_clean=read.csv("dat_clean_modified_zscore_anchoveta.csv")


dat_clean$group <- factor(dat_clean$Subclass_n,      # Reordering group factor levels
                         levels = c("Moda 3.5 cm", "Moda 4 cm", "Moda 5 cm", "Moda 7.5 cm","Moda 10.5 cm", "Moda 11 cm", "Moda 12 cm","Moda 12.5 cm","Moda 13 cm","Moda 13.5 cm"),labels = c("3.5", "4", "5", "7.5","10.5","11","12","12.5","13","13.5"))

dat_clean$Banda <- factor(dat_clean$Banda,
  levels = c("35-45","45-90","90-170","170-260"),labels = c("35-45","45-90","90-170","170-260"))

dat=dat_clean
anxiety <- dat %>%
  select(group,Frequency,Value)%>%
  mutate(Frecuencia=round(as.numeric(Frequency,0)),Sv=round(Value,2),Class=group)%>%
  #rename(pretest = Frecuencia, posttest = Valor, group=Class) %>%
  drop_na()%>%
  mutate(Frecuencia=as.numeric(Frecuencia))
library(dplyr)

# Especifica el tamaño del subconjunto balanceado
tamaño_subconjunto <- 1000

# Realiza el muestreo aleatorio y balanceado
subset_balanceado <- anxiety %>%
  group_by(Class) %>%
  sample_n(tamaño_subconjunto, replace = T) %>%
  ungroup()

# Verifica el tamaño del subconjunto balanceado
nrow(subset_balanceado)
[1] 10000
anxiety=subset_balanceado

# Ahora `subset_balanceado` contiene un subconjunto aleatorio y balanceado de tus datos.

Comprobar supuestos Supuesto de linealidad

Comprobar supuestos

Supuesto de linealidad

Cree un diagrama de dispersión entre la covariable (es decir, ) y la variable de resultado (es decir, frecuencia). Agregue líneas de regresión, muestre las ecuaciones correspondientes y el R2 por grupos.

ggscatter(
  anxiety, x = "Frecuencia", y = "Sv",
  color = "Class", add = "reg.line",size = 0.5, alpha=0.5
  )+
  stat_regline_equation(
    aes(label =  paste(..eq.label.., ..rr.label.., sep = "~~~~"), color = Class)
    )+
  theme_bw()
Warning: The dot-dot notation (`..eq.label..`) was deprecated in ggplot2 3.4.0.
ℹ Please use `after_stat(eq.label)` instead.
ℹ The deprecated feature was likely used in the ggpubr package.
  Please report the issue at <https://github.com/kassambara/ggpubr/issues>.

Hubo una relación lineal entre la puntuación de ansiedad antes y después de la prueba para cada grupo de entrenamiento, según se evaluó mediante la inspección visual de un diagrama de dispersión.

Homogeneidad de las pendientes de regresión

Esta suposición verifica que no haya interacción significativa entre la covariable y la variable de agrupación. Esto se puede evaluar de la siguiente manera:

anxiety %>% anova_test(Sv ~ Class*Frecuencia)
ANOVA Table (type II tests)

            Effect DFn  DFd       F        p p<.05   ges
1            Class   9 9980 338.697 0.00e+00     * 0.234
2       Frecuencia   1 9980 308.810 4.18e-68     * 0.030
3 Class:Frecuencia   9 9980  40.760 3.81e-72     * 0.035

Hubo homogeneidad de pendientes de regresión ya que el término de interacción no fue estadísticamente significativo, F(4, 4990) = 76.544, p = *…..en realidad fue significativa

Normalidad de los residuos

En primer lugar, debe calcular el modelo mediante . En R, puede aumentar fácilmente sus datos para agregar valores ajustados y residuales mediante la función [paquete de escobas]. Llamemos a la salida porque contiene varias métricas útiles para el diagnóstico de regresión.lm()augment(model)model.metrics

Normality of residuals You first need to compute the model using lm(). In R, you can easily augment your data to add fitted values and residuals by using the function augment(model) [broom package]. Let’s call the output model.metrics because it contains several metrics useful for regression diagnostics.

# Fit the model, the covariate goes first
model <- lm(Sv ~ Frecuencia + Class, data = anxiety)
model

Call:
lm(formula = Sv ~ Frecuencia + Class, data = anxiety)

Coefficients:
(Intercept)   Frecuencia       Class4       Class5     Class7.5    Class10.5  
  -52.77201     -0.01997     -2.05873     -3.58675     -0.91162     -2.25655  
    Class11      Class12    Class12.5      Class13    Class13.5  
   -1.14977      1.59731      4.82509      6.08319      9.20498  
# Inspect the model diagnostic metrics
model.metrics <- augment(model) %>%
  select(-.hat, -.sigma, -.fitted, -.fitted) # Remove details

model.metrics 
# A tibble: 10,000 × 6
      Sv Frecuencia Class  .resid     .cooksd .std.resid
   <dbl>      <dbl> <fct>   <dbl>       <dbl>      <dbl>
 1 -47.5        176 3.5     8.83  0.000134        1.21  
 2 -41.9        213 3.5    15.1   0.000422        2.07  
 3 -51.3         64 3.5     2.75  0.0000156       0.377 
 4 -47.7        201 3.5     9.12  0.000149        1.25  
 5 -59.4        241 3.5    -1.82  0.00000666     -0.249 
 6 -58.2        244 3.5    -0.545 0.000000608    -0.0747
 7 -65.7         59 3.5   -11.7   0.000291       -1.61  
 8 -65.0        112 3.5   -10.0   0.000180       -1.37  
 9 -57.0        131 3.5    -1.62  0.00000456     -0.222 
10 -50.9         60 3.5     3.08  0.0000199       0.422 
# ℹ 9,990 more rows
#Assess normality of residuals using shapiro wilk test
#shapiro_test(model.metrics$.resid)

La prueba de Shapiro Wilk no fue significativa (p > 0,05), por lo que podemos suponer normalidad de los residuos

Homogeneidad de las varianzas

Homogeneidad de las varianzas ANCOVA asume que la varianza de los residuos es igual para todos los grupos. Esto se puede comprobar mediante el test de Levene:

Homogeneity of variances ANCOVA assumes that the variance of the residuals is equal for all groups. This can be checked using the Levene’s test:

model.metrics %>% levene_test(.resid ~ Class)
# A tibble: 1 × 4
    df1   df2 statistic         p
  <int> <int>     <dbl>     <dbl>
1     9  9990      91.7 5.74e-165

La prueba de Levene no fue significativa (p > 0,05), por lo que podemos suponer homogeneidad de las varianzas residuales para todos los grupos.

The Levene’s test was not significant (p > 0.05), so we can assume homogeneity of the residual variances for all groups.

Outliers

An outlier is a point that has an extreme outcome variable value. The presence of outliers may affect the interpretation of the model.

Outliers can be identified by examining the standardized residual (or studentized residual), which is the residual divided by its estimated standard error. Standardized residuals can be interpreted as the number of standard errors away from the regression line.

Las observaciones cuyos residuos estandarizados son mayores que 3 en valor absoluto son posibles valores atípicos

model.metrics %>% 
  filter(abs(.std.resid) > 3) %>%
  as.data.frame()
       Sv Frecuencia Class    .resid      .cooksd .std.resid
1  -76.16         54   3.5 -22.30960 0.0010710463  -3.057176
2  -76.49         43   3.5 -22.85927 0.0011774103  -3.132593
3  -76.16         54   3.5 -22.30960 0.0010710463  -3.057176
4  -76.78         53   3.5 -22.94957 0.0011379990  -3.144882
5  -31.16        165   7.5  25.81871 0.0011397846   3.537587
6  -32.03        250   7.5  26.64617 0.0014644905   3.651339
7  -34.47        192   7.5  23.04790 0.0009320506   3.157982
8  -30.82         46   7.5  23.78226 0.0012777165   3.259083
9  -32.94        146   7.5  23.65927 0.0009604785   3.241715
10 -30.99        196   7.5  26.60778 0.0012506729   3.645764
11 -32.19        174   7.5  24.96844 0.0010709133   3.421094
12 -33.50        218   7.5  24.53712 0.0011179833   3.362134
13 -31.73        126   7.5  24.46987 0.0010512854   3.352819
14 -33.48        124   7.5  22.67993 0.0009061325   3.107570
15 -82.37         56  10.5 -26.22311 0.0014820108  -3.593464
16 -80.83         62  10.5 -24.56329 0.0012695329  -3.365961
17 -81.60         53  10.5 -25.51302 0.0014202087  -3.496185
18 -81.29         61  10.5 -25.04326 0.0013248329  -3.431741
19 -78.58         69  10.5 -22.17349 0.0010071622  -3.038434
20 -33.55         47  10.5  22.41716 0.0011244475   3.071993
21 -79.29         67  10.5 -22.92343 0.0010845700  -3.141212
22 -81.50         52  10.5 -25.43299 0.0014171791  -3.485227
23 -81.40         51  10.5 -25.35296 0.0014141592  -3.474269
24 -79.97         65  10.5 -23.64338 0.0011626038  -3.239881
25 -33.45         46  10.5  22.49719 0.0011373424   3.082969
26 -74.12         45    12 -22.04664 0.0010936680  -3.021229
27 -30.96         91    12  22.03199 0.0009208516   3.018909
28 -74.05         35    12 -22.17634 0.0011561806  -3.039092
29 -75.08         83    12 -22.24777 0.0009628908  -3.048520
30 -79.72         53    12 -27.48688 0.0016437330  -3.766666
31 -77.75         38    12 -25.81643 0.0015461171  -3.537905
32 -29.72         46    12  22.37333 0.0011215089   3.065989
33 -74.57         36    12 -22.67637 0.0012035208  -3.107608
34 -78.61         51    12 -26.41682 0.0015308779  -3.620050
35 -30.17        160    12  24.19993 0.0010006817   3.315787
36 -26.60         46  12.5  22.26555 0.0010839276   3.051171
37 -23.28         91  13.5  22.10431 0.0008779175   3.028731
38 -24.69        169  13.5  22.25199 0.0008685524   3.048927
39 -19.33         46  13.5  25.15566 0.0013031150   3.447090
40 -23.28         91  13.5  22.10431 0.0008779175   3.028731
41 -21.61         92  13.5  23.79428 0.0010151079   3.260287

COMPUTATION

El orden de las variables es importante a la hora de calcular ANCOVA. Primero desea eliminar el efecto de la covariable, es decir, desea controlarla, antes de ingresar su variable o interés principal.

¡La covariable va primero (y no hay interacción)! Si no lo haces en orden, obtendrás resultados diferentes.

#COMPUTATION
res.aov <- anxiety %>%
anova_test(Sv ~ Frecuencia + Class)
get_anova_table(res.aov)
ANOVA Table (type II tests)

      Effect DFn  DFd       F        p p<.05   ges
1 Frecuencia   1 9989 298.130 7.56e-66     * 0.029
2      Class   9 9989 326.984 0.00e+00     * 0.228

Después del ajuste por la puntuación de ansiedad previa a la prueba, hubo una diferencia estadísticamente significativa en la puntuación de ansiedad posterior a la prueba entre los grupos, F(4, 4994) = 580.579, p < 0,0001 *.

POST HOC TEST

Se pueden realizar comparaciones por pares para identificar qué grupos son diferentes. Se aplica la corrección de pruebas múltiples de Bonferroni. Esto se puede hacer fácilmente usando la función [paquete rstatix], un envoltorio alrededor del paquete, que debe instalarse. Emmeans significa medias marginales estimadas (también conocidas como medias mínimas cuadráticas o medias ajustadas).emmeans_test()emmeans

#POST HOC TEST
# Pairwise comparisons
# Pairwise comparisons
library(emmeans)
Warning: package 'emmeans' was built under R version 4.3.3
Welcome to emmeans.
Caution: You lose important information if you filter this package's results.
See '? untidy'
pwc <- anxiety %>% 
  emmeans_test(
    Sv ~ Class, covariate = Frecuencia,
    p.adjust.method = "bonferroni"
    )
pwc
# A tibble: 45 × 9
   term     .y.   group1 group2    df statistic         p     p.adj p.adj.signif
 * <chr>    <chr> <chr>  <chr>  <dbl>     <dbl>     <dbl>     <dbl> <chr>       
 1 Frecuen… Sv    3.5    4       9989      6.30 3.03e- 10 1.36e-  8 ****        
 2 Frecuen… Sv    3.5    5       9989     11.0  6.62e- 28 2.98e- 26 ****        
 3 Frecuen… Sv    3.5    7.5     9989      2.79 5.26e-  3 2.37e-  1 ns          
 4 Frecuen… Sv    3.5    10.5    9989      6.91 5.15e- 12 2.32e- 10 ****        
 5 Frecuen… Sv    3.5    11      9989      3.52 4.32e-  4 1.94e-  2 *           
 6 Frecuen… Sv    3.5    12      9989     -4.89 1.02e-  6 4.58e-  5 ****        
 7 Frecuen… Sv    3.5    12.5    9989    -14.8  7.05e- 49 3.17e- 47 ****        
 8 Frecuen… Sv    3.5    13      9989    -18.6  3.84e- 76 1.73e- 74 ****        
 9 Frecuen… Sv    3.5    13.5    9989    -28.1  1.55e-167 6.95e-166 ****        
10 Frecuen… Sv    4      5       9989      4.68 2.93e-  6 1.32e-  4 ***         
# ℹ 35 more rows
# Display the adjusted means of each group
# Also called as the estimated marginal means (emmeans)
get_emmeans(pwc)
# A tibble: 10 × 8
   Frecuencia Class emmean    se    df conf.low conf.high method      
        <dbl> <fct>  <dbl> <dbl> <dbl>    <dbl>     <dbl> <chr>       
 1       154. 3.5    -55.8 0.231  9989    -56.3     -55.4 Emmeans test
 2       154. 4      -57.9 0.231  9989    -58.4     -57.5 Emmeans test
 3       154. 5      -59.4 0.231  9989    -59.9     -59.0 Emmeans test
 4       154. 7.5    -56.8 0.231  9989    -57.2     -56.3 Emmeans test
 5       154. 10.5   -58.1 0.231  9989    -58.6     -57.7 Emmeans test
 6       154. 11     -57.0 0.231  9989    -57.5     -56.5 Emmeans test
 7       154. 12     -54.3 0.231  9989    -54.7     -53.8 Emmeans test
 8       154. 12.5   -51.0 0.231  9989    -51.5     -50.6 Emmeans test
 9       154. 13     -49.8 0.231  9989    -50.2     -49.3 Emmeans test
10       154. 13.5   -46.6 0.232  9989    -47.1     -46.2 Emmeans test

Los datos se ajustan a la media +/- error estándar. La puntuación media de ansiedad fue estadísticamente significativa mayor en el grp1 (16,4 +/- 0,15) en comparación con el grp2 (15,8 +/- 0,12) y el grp3 (13,5 +/_ 0,11), p < 0,001.

Informe

Se realizó un ANCOVA para determinar el efecto de los ejercicios en la puntuación de ansiedad después de controlar la puntuación de ansiedad basal de los participantes.

Después del ajuste por la puntuación de ansiedad previa a la prueba, hubo una diferencia estadísticamente significativa en la puntuación de ansiedad posterior a la prueba entre los grupos, F(4, 4994) = 580.579, p < 0,0001 *.

El análisis post hoc se realizó con un ajuste de Bonferroni. La puntuación media de ansiedad fue estadísticamente significativa mayor en el grp1 (16,4 +/- 0,15) en comparación con el grp2 (15,8 +/- 0,12) y el grp3 (13,5 +/_ 0,11), p < 0,001.

# Visualization: line plots with p-values
pwc <- pwc %>% add_xy_position(x = "Class", fun = "mean_se")

ggline(get_emmeans(pwc), x = "Class", y = "emmean") +
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high, color=Class), width = 1) + 
  stat_pvalue_manual(pwc, hide.ns = TRUE, tip.length = FALSE) +
  labs(
    subtitle = get_test_label(res.aov, detailed = TRUE),
    caption = get_pwc_label(pwc)
  )+
  theme_presentation(base_size = 11)+
  
  
    scale_color_manual(name="Longitud (cm)",values =c("#5f5f5f","#0000ff","#000080","#00bf00","#008000","#ffff00","#ff8000","#ff00bf","#ff0000","#a6533c"))+
  
    #scale_color_viridis_d(option = "C")+
  # Modificación para rotar las etiquetas del eje x
theme(axis.text.x = element_text(angle = 0, vjust = 0.5, hjust=1),legend.position = "none")+
  labs(x="Longitud (cm)",y="Emmean (Sv,dB)")

Referencias para buscar en la web: ANCOVA

1-s2.0-S0022191021001335-mmc1.docx (live.com)

Acclimation, duration and intensity of cold exposure determine the rate of cold stress accumulation and mortality in Drosophila suzukii - ScienceDirect