R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

summary(cars)
##      speed           dist       
##  Min.   : 4.0   Min.   :  2.00  
##  1st Qu.:12.0   1st Qu.: 26.00  
##  Median :15.0   Median : 36.00  
##  Mean   :15.4   Mean   : 42.98  
##  3rd Qu.:19.0   3rd Qu.: 56.00  
##  Max.   :25.0   Max.   :120.00
# Instalar una sola vez, si es necesario
# install.packages(c(
#   "tidyverse", "rstatix", "knitr",
#   "broom", "effectsize", "ggpubr"
# ))

library(tidyverse)
## ── 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(rstatix)
## 
## Adjuntando el paquete: 'rstatix'
## 
## The following object is masked from 'package:stats':
## 
##     filter
library(knitr)
library(broom)
library(effectsize)
## 
## Adjuntando el paquete: 'effectsize'
## 
## The following objects are masked from 'package:rstatix':
## 
##     cohens_d, eta_squared, omega_squared
library(ggpubr)

options(
  digits = 4,
  scipen = 999
)

alpha <- 0.05

theme_set(
  theme_classic(base_size = 12)
)
library(readxl)
datos <- read_excel("D:/usuario nuevo/Downloads/datos.xlsx")
View(datos)
datos <- tibble(
  resina = rep(
    c(
      "Transcend",
      "EasyMatch",
      "SimpliShade",
      "Vittra",
      "Filtek Z350 XT"
    ),
    each = 8
  ),

  contraccion = c(
    # Transcend
    2.555022, 2.715731, 1.980722, 1.444973,
    1.025596, 1.192092, 1.292739, 2.029705,

    # EasyMatch
    0.499976, 0.615494, 0.723248, 0.525220,
    0.084800, 1.818979, 1.897403, 1.091361,

    # SimpliShade
    2.833384, 1.934640, 2.776268, 2.933820,
    2.611012, 3.917132, 4.572182, 4.684513,

    # Vittra
    3.056665, 1.013055, 1.187163, 2.213193,
    1.324839, 0.830841, 1.556931, 1.329415,

    # Filtek Z350 XT
    3.379659, 2.053056, 1.708239, 1.976309,
    2.373803, 2.004132, 1.770787, 2.078057
  )
) |>
  mutate(
    resina = factor(
      resina,
      levels = c(
        "Transcend",
        "EasyMatch",
        "SimpliShade",
        "Vittra",
        "Filtek Z350 XT"
      )
    )
  )

# Verificar la base
glimpse(datos)
## Rows: 40
## Columns: 2
## $ resina      <fct> Transcend, Transcend, Transcend, Transcend, Transcend, Tra…
## $ contraccion <dbl> 2.5550, 2.7157, 1.9807, 1.4450, 1.0256, 1.1921, 1.2927, 2.…
# Número de observaciones por resina
datos |>
  count(resina) |>
  kable(
    caption = "Número de observaciones por material"
  )
Número de observaciones por material
resina n
Transcend 8
EasyMatch 8
SimpliShade 8
Vittra 8
Filtek Z350 XT 8

##Verificación de calidad de los datos

# Dimensiones
cat("Número de observaciones:", nrow(datos), "\n")
## Número de observaciones: 40
cat("Número de resinas:", n_distinct(datos$resina), "\n")
## Número de resinas: 5
# Datos faltantes
datos |>
  summarise(
    observaciones = n(),
    valores_faltantes = sum(is.na(contraccion)),
    valores_no_finitos = sum(!is.finite(contraccion)),
    valores_negativos = sum(contraccion < 0, na.rm = TRUE)
  ) |>
  kable(caption = "Control de calidad de la variable principal")
Control de calidad de la variable principal
observaciones valores_faltantes valores_no_finitos valores_negativos
40 0 0 0
# Valores individuales
datos |>
  arrange(resina, contraccion) |>
  kable(
    digits = 4,
    caption = "Observaciones individuales de contracción (%)"
  )
Observaciones individuales de contracción (%)
resina contraccion
Transcend 1.0256
Transcend 1.1921
Transcend 1.2927
Transcend 1.4450
Transcend 1.9807
Transcend 2.0297
Transcend 2.5550
Transcend 2.7157
EasyMatch 0.0848
EasyMatch 0.5000
EasyMatch 0.5252
EasyMatch 0.6155
EasyMatch 0.7232
EasyMatch 1.0914
EasyMatch 1.8190
EasyMatch 1.8974
SimpliShade 1.9346
SimpliShade 2.6110
SimpliShade 2.7763
SimpliShade 2.8334
SimpliShade 2.9338
SimpliShade 3.9171
SimpliShade 4.5722
SimpliShade 4.6845
Vittra 0.8308
Vittra 1.0131
Vittra 1.1872
Vittra 1.3248
Vittra 1.3294
Vittra 1.5569
Vittra 2.2132
Vittra 3.0567
Filtek Z350 XT 1.7082
Filtek Z350 XT 1.7708
Filtek Z350 XT 1.9763
Filtek Z350 XT 2.0041
Filtek Z350 XT 2.0531
Filtek Z350 XT 2.0781
Filtek Z350 XT 2.3738
Filtek Z350 XT 3.3797

##Análisis descriptivo

tabla_descriptiva <- datos |>
  group_by(resina) |>
  summarise(
    n = n(),
    media = mean(contraccion),
    DE = sd(contraccion),
    mediana = median(contraccion),
    Q1 = quantile(contraccion, 0.25),
    Q3 = quantile(contraccion, 0.75),
    RIC = IQR(contraccion),
    minimo = min(contraccion),
    maximo = max(contraccion),
    .groups = "drop"
  )

tabla_descriptiva |>
  mutate(
    across(where(is.numeric), ~ round(.x, 3))
  ) |>
  kable(
    caption = "Estadísticos descriptivos de la contracción por polimerización (%)"
  )
Estadísticos descriptivos de la contracción por polimerización (%)
resina n media DE mediana Q1 Q3 RIC minimo maximo
Transcend 8 1.780 0.637 1.713 1.268 2.161 0.893 1.026 2.716
EasyMatch 8 0.907 0.649 0.669 0.519 1.273 0.754 0.085 1.897
SimpliShade 8 3.283 0.991 2.884 2.735 4.081 1.346 1.935 4.685
Vittra 8 1.564 0.731 1.327 1.144 1.721 0.577 0.831 3.057
Filtek Z350 XT 8 2.168 0.530 2.029 1.925 2.152 0.227 1.708 3.380

#- Una media más alta indica mayor contracción promedio en las observaciones analizadas. #- Una desviación estándar elevada indica mayor dispersión de los resultados dentro del grupo. #- La diferencia entre media y mediana puede sugerir asimetría. #- El rango intercuartílico muestra la amplitud del 50 % central de las mediciones. #En estos datos, SimpliShade tiene una media de 3,283 % y una mediana de 2,884 %. EasyMatch tiene una media de 0,907 % y una mediana de 0,669 %. Esta diferencia descriptiva es importante, pero no debe interpretarse automáticamente como una diferencia estadísticamente significativa ni como una diferencia de relevancia clínica.

##Gráfico de distribución por material

ggplot(datos, aes(x = resina, y = contraccion)) +
  geom_boxplot(
    aes(fill = resina),
    alpha = 0.45,
    width = 0.55,
    outlier.shape = NA
  ) +
  geom_jitter(
    width = 0.10,
    size = 2.4,
    alpha = 0.85
  ) +
  labs(
    title = "Distribución de la contracción por polimerización",
    subtitle = "Cinco resinas dentales",
    x = "Material restaurador",
    y = "Contracción por polimerización (%)"
  ) +
  theme(
    legend.position = "none",
    axis.text.x = element_text(
      angle = 20,
      hjust = 1
    )
  )

#la línea central de cada caja representa la mediana; la caja representa el rango intercuartílico y los puntos son las observaciones individuales. Se aprecia una tendencia a valores más altos en SimpliShade y más bajos en EasyMatch. La variabilidad de cada material debe considerarse antes de establecer conclusiones sobre las diferencias entre grupos

##Evaluación de los supuestos estadísticos #Normalidad mediante Shapiro–Wilk

tabla_normalidad <- datos |>
  group_by(resina) |>
  shapiro_test(contraccion) |>
  ungroup() |>
  mutate(
    interpretacion = if_else(
      p < alpha,
      "Evidencia contra la normalidad",
      "Sin evidencia suficiente contra la normalidad"
    )
  )

tabla_normalidad |>
  mutate(
    across(c(statistic, p), ~ round(.x, 4))
  ) |>
  kable(
    caption = "Prueba de normalidad de Shapiro-Wilk por material"
  )
Prueba de normalidad de Shapiro-Wilk por material
resina variable statistic p interpretacion
Transcend contraccion 0.9151 0.3914 Sin evidencia suficiente contra la normalidad
EasyMatch contraccion 0.8879 0.2236 Sin evidencia suficiente contra la normalidad
SimpliShade contraccion 0.9010 0.2953 Sin evidencia suficiente contra la normalidad
Vittra contraccion 0.8569 0.1119 Sin evidencia suficiente contra la normalidad
Filtek Z350 XT contraccion 0.7609 0.0108 Evidencia contra la normalidad

#Hipótesis de la prueba: #- \(H_0\): los datos del grupo proceden de una distribución normal. #- \(H_1\): los datos del grupo no proceden de una distribución normal. #Criterio de interpretación: si \(p<0,05\), se rechaza la hipótesis de normalidad para ese grupo. Si \(p\geq0,05\), no hay evidencia suficiente para rechazarla; esto no demuestra que la distribución sea normal.

#En el cálculo preliminar, Filtek Z350 XT presentó un valor de \(p\) cercano a 0,011, lo que constituye evidencia contra la normalidad. Los otros cuatro grupos no mostraron evidencia estadística suficiente contra ese supuesto. Esto respalda la decisión de examinar también una alternativa no paramétrica.

##Gráficos Q-Q

ggplot(datos, aes(sample = contraccion)) +
  stat_qq() +
  stat_qq_line(color = "red") +
  facet_wrap(~ resina, scales = "free") +
  labs(
    title = "Gráficos Q-Q de la contracción por material",
    x = "Cuantiles teóricos",
    y = "Cuantiles observados"
  ) +
  theme_classic()

#si los puntos siguen aproximadamente la línea de referencia, la distribución es compatible con la normalidad. Desviaciones sistemáticas, curvaturas o puntos muy alejados de la línea pueden indicar asimetría o valores extremos.

##Homogeneidad de varianzas

prueba_levene <- datos |>
  levene_test(contraccion ~ resina, center = median)

prueba_levene |>
  mutate(
    across(where(is.numeric), ~ round(.x, 4))
  ) |>
  kable(
    caption = "Prueba de homogeneidad de varianzas de Levene"
  )
Prueba de homogeneidad de varianzas de Levene
df1 df2 statistic p
4 35 0.7331 0.5756

#Hipótesis: #- \(H_0\): las varianzas de los cinco materiales son iguales. #- \(H_1\): al menos una varianza es diferente. #El cálculo preliminar produjo \(p\approx0,576\). Por tanto, no hay evidencia estadística suficiente para rechazar la homogeneidad de varianzas. Esto no prueba que las varianzas sean idénticas.

#Decisión metodológica: debido a la evidencia contra la normalidad en uno de los grupos y al tamaño muestral reducido, utilizaremos Kruskal–Wallis como análisis principal de comparación global y Dunn con ajuste de Holm para las comparaciones por pares.

##Comparación global de las cinco resinas #Prueba de Kruskal–Wallis

resultado_kw <- kruskal.test(
  contraccion ~ resina,
  data = datos
)

tabla_kw <- tibble(
  prueba = "Kruskal-Wallis",
  estadistico_H = unname(resultado_kw$statistic),
  grados_libertad = unname(resultado_kw$parameter),
  valor_p = resultado_kw$p.value,
  decision = if_else(
    resultado_kw$p.value < alpha,
    "Rechazar H0",
    "No rechazar H0"
  )
)

tabla_kw |>
  mutate(
    estadistico_H = round(estadistico_H, 3),
    valor_p = signif(valor_p, 4)
  ) |>
  kable(
    caption = "Comparación global de la contracción por polimerización"
  )
Comparación global de la contracción por polimerización
prueba estadistico_H grados_libertad valor_p decision
Kruskal-Wallis 22.1 4 0.0002 Rechazar H0

#Las hipótesis son: #- \(H_0\): las distribuciones de contracción de las cinco resinas son iguales. #- \(H_1\): al menos una distribución difiere de las demás. #En el caso de distribuciones con formas y dispersiones similares, la prueba se puede interpretar como una comparación de localización, incluida la mediana. En general, Kruskal–Wallis contrasta las distribuciones, no exclusivamente las medias.

#Resultado preliminar: \(H\approx22,103\), con 4 grados de libertad y \(p\approx0,000191\).

#Interpretación: como \(p<0,05\), se rechaza la hipótesis nula. Existe evidencia estadística de diferencias en la distribución de la contracción entre al menos dos de los cinco materiales.

#Este resultado global no indica por sí solo qué pares de resinas son diferentes. Para responder esa pregunta se necesita el análisis post hoc.

##Tamaño del efecto

H <- as.numeric(resultado_kw$statistic)
N <- nrow(datos)
k <- n_distinct(datos$resina)

epsilon2 <- max(0, (H - k + 1) / (N - k))

tibble(
  estadistico_H = H,
  N = N,
  grupos = k,
  epsilon_cuadrado = epsilon2
) |>
  mutate(
    across(where(is.numeric), ~ round(.x, 4))
  ) |>
  kable(
    caption = "Estimación del tamaño del efecto para Kruskal-Wallis"
  )
Estimación del tamaño del efecto para Kruskal-Wallis
estadistico_H N grupos epsilon_cuadrado
22.1 40 5 0.5172

#El valor preliminar es \(\E^2\approx0,517\). Este resultado sugiere una separación importante entre los rangos de los grupos en estos datos. Debe interpretarse como una estimación descriptiva del tamaño del efecto, no como el porcentaje de contracción explicado causalmente por el material ni como una medida directa de importancia clínica.

##Comparaciones múltiples entre resinas #Prueba post hoc de Dunn con ajuste de Holm

resultado_dunn <- datos |>
  dunn_test(
    contraccion ~ resina,
    p.adjust.method = "holm"
  ) |>
  mutate(
    diferencia_significativa = if_else(
      p.adj < alpha,
      "Sí",
      "No"
    )
  )

resultado_dunn |>
  select(
    group1,
    group2,
    statistic,
    p,
    p.adj,
    diferencia_significativa
  ) |>
  mutate(
    across(c(statistic, p, p.adj), ~ signif(.x, 4))
  ) |>
  kable(
    caption = "Comparaciones por pares mediante Dunn con corrección de Holm"
  )
Comparaciones por pares mediante Dunn con corrección de Holm
group1 group2 statistic p p.adj diferencia_significativa
Transcend EasyMatch -1.9890 0.0467 0.2803 No
Transcend SimpliShade 2.4590 0.0139 0.0974 No
Transcend Vittra -0.5560 0.5782 0.6935 No
Transcend Filtek Z350 XT 0.9409 0.3467 0.6935 No
EasyMatch SimpliShade 4.4480 0.0000 0.0001 Sí
EasyMatch Vittra 1.4330 0.1519 0.6447 No
EasyMatch Filtek Z350 XT 2.9300 0.0034 0.0271 Sí
SimpliShade Vittra -3.0150 0.0026 0.0231 Sí
SimpliShade Filtek Z350 XT -1.5180 0.1289 0.6447 No
Vittra Filtek Z350 XT 1.4970 0.1344 0.6447 No

#El ajuste de Holm controla el error familiar asociado a realizar varias comparaciones. Para la interpretación, debe utilizarse la columna p.adj, no solamente el valor p sin ajustar. #- EasyMatch frente a SimpliShade: SimpliShade presenta valores de contracción más altos. #- EasyMatch frente a Filtek Z350 XT: Filtek Z350 XT presenta valores de contracción más altos. #- SimpliShade frente a Vittra: SimpliShade presenta valores de contracción más altos. #Las otras siete comparaciones no alcanzan significación estadística después del ajuste de Holm. Esto no demuestra que los materiales sean equivalentes; significa que el estudio no encontró evidencia suficiente para establecer una diferencia en esas comparaciones bajo el procedimiento utilizado.

##Visualización de las diferencias estadísticas #Gráfico de medianas e intervalos intercuartílicos

resumen_grafico <- datos |>
  group_by(resina) |>
  summarise(
    mediana = median(contraccion),
    Q1 = quantile(contraccion, 0.25),
    Q3 = quantile(contraccion, 0.75),
    .groups = "drop"
  )

ggplot(
  resumen_grafico,
  aes(x = resina, y = mediana)
) +
  geom_errorbar(
    aes(ymin = Q1, ymax = Q3),
    width = 0.15,
    linewidth = 0.8
  ) +
  geom_point(size = 3) +
  labs(
    title = "Mediana e intervalo intercuartílico de la contracción",
    x = "Material restaurador",
    y = "Contracción (%)"
  ) +
  theme(
    axis.text.x = element_text(
      angle = 20,
      hjust = 1
    )
  )

#Este gráfico complementa el diagrama de cajas y facilita la comparación de la tendencia central y la dispersión de los cinco materiales. #cada punto representa la mediana del grupo y cada barra vertical corresponde al intervalo entre el primer y el tercer cuartil. Una posición más alta representa mayor contracción central. La superposición de estos intervalos no debe utilizarse como una prueba formal de significación estadística; para eso se utilizarán los resultados de Dunn.

##Resumen estadístico para el artículo

cat(
  sprintf(
    paste0(
      "Se analizaron %d observaciones correspondientes a %d materiales. ",
      "La prueba de Kruskal-Wallis indicó ",
      "H = %.3f, con %d grados de libertad y p = %.6f. ",
      "El tamaño del efecto estimado mediante epsilon cuadrado fue %.3f. "
    ),
    nrow(datos),
    n_distinct(datos$resina),
    as.numeric(resultado_kw$statistic),
    as.numeric(resultado_kw$parameter),
    resultado_kw$p.value,
    epsilon2
  )
)
## Se analizaron 40 observaciones correspondientes a 5 materiales. La prueba de Kruskal-Wallis indicó H = 22.103, con 4 grados de libertad y p = 0.000191. El tamaño del efecto estimado mediante epsilon cuadrado fue 0.517.
cat("\n\nComparaciones significativas después del ajuste de Holm:\n\n")
## 
## 
## Comparaciones significativas después del ajuste de Holm:
resultado_dunn |>
  filter(p.adj < alpha) |>
  transmute(
    Comparacion = paste(group1, "vs.", group2),
    p_ajustado = signif(p.adj, 4)
  ) |>
  print()
## # A tibble: 3 × 2
##   Comparacion                  p_ajustado
##   <chr>                             <dbl>
## 1 EasyMatch vs. SimpliShade     0.0000866
## 2 EasyMatch vs. Filtek Z350 XT  0.0271   
## 3 SimpliShade vs. Vittra        0.0231

#Análisis estadístico #La variable principal fue el porcentaje de contracción por polimerización de cinco materiales restauradores: Transcend, EasyMatch, SimpliShade, Vittra y Filtek Z350 XT. Se analizaron ocho observaciones por material, para un total de 40 observaciones.

#Se calcularon estadísticos descriptivos de tendencia central y dispersión, incluyendo media, desviación estándar, mediana y rango intercuartílico. La distribución de la variable se examinó mediante gráficos y la prueba de Shapiro–Wilk. La homogeneidad de varianzas se evaluó con la prueba de Levene centrada en la mediana.

#Debido al tamaño muestral reducido y a la evidencia de desviación de la normalidad en uno de los grupos, se utilizó la prueba de Kruskal–Wallis para evaluar diferencias globales entre materiales. Cuando se detectaron diferencias estadísticamente significativas, se realizaron comparaciones por pares mediante la prueba de Dunn, con ajuste de Holm para controlar el error por comparaciones múltiples.

#Se estableció un nivel de significación de 0,05. Adicionalmente, se estimó epsilon cuadrado como medida del tamaño del efecto. Los análisis se realizaron en RStudio mediante R.

#A partir de los resultados preliminares, se puede plantear la siguiente interpretación: #1. Variación entre materiales. Los porcentajes de contracción no se distribuyeron de forma idéntica entre las cinco resinas, según la prueba de Kruskal–Wallis. #2. Mayor contracción observada. SimpliShade presentó la media y la mediana más elevadas en la muestra analizada. Este resultado describe el comportamiento de las observaciones y no implica necesariamente que el material sea clínicamente inferior. #3. Menor contracción observada. EasyMatch presentó la menor media y mediana. Sin embargo, la dispersión de sus resultados debe tenerse en cuenta al valorar su reproducibilidad. #4. Diferencias entre pares. Las comparaciones post hoc identificaron diferencias entre EasyMatch y SimpliShade, EasyMatch y Filtek Z350 XT, y SimpliShade y Vittra. Las demás comparaciones no alcanzaron significación después de la corrección por multiplicidad.