1. Cargar la base de datos

datos <- read_excel("citricos.xlsx")

1.a Cantidad de observaciones y variables

cat("Cantidad de variables:", ncol(datos), "\n")
## Cantidad de variables: 17
cat("Cantidad de observaciones:", nrow(datos))
## Cantidad de observaciones: 750

La base de datos “citricos.xlsx” tiene 17 variables y 750 observaciones.

1.b Clasificación de variables

El código cuenta cuantas variables son numéricas, cuantas son “caracteres” y cuantas “factores”. Luego da la los nombres de variables numericas por un lado y la de variables categóricas por otro.

# Revisar estructura
str(datos)
## tibble [750 × 17] (S3: tbl_df/tbl/data.frame)
##  $ id              : num [1:750] 1 2 3 4 5 6 7 8 9 10 ...
##  $ variedad        : chr [1:750] "Clemenules" "Clemenules" "Clemenules" "Clemenules" ...
##  $ peso_antes      : num [1:750] 145 149 120 150 136 ...
##  $ diametro_antes  : num [1:750] 57.4 56.1 52.1 54.8 54.3 56.8 54 58.1 54 58.3 ...
##  $ peso_despues    : num [1:750] 139 152 153 140 130 ...
##  $ diametro_despues: num [1:750] 67.6 68.5 69.1 58.4 69.7 64.9 67 65.5 69 65.3 ...
##  $ color_nivel     : num [1:750] 4 1 3 3 5 4 4 1 3 4 ...
##  $ color_desc      : chr [1:750] "Naranja claro" "Verde completo" "Amarillo pálido" "Amarillo pálido" ...
##  $ madurez         : chr [1:750] "Maduro" "Muy inmaduro" "Semimaduro" "Semimaduro" ...
##  $ danio_nivel     : num [1:750] 0 0 0 1 0 0 1 0 1 0 ...
##  $ danio_desc      : chr [1:750] "Sin daño" "Sin daño" "Sin daño" "Daño leve" ...
##  $ fertilizante    : chr [1:750] "Mixto" "Organico" "Quimico" "Quimico" ...
##  $ humedad_suelo   : num [1:750] 16.7 24.2 33.7 31.9 29.3 17.5 26.9 34.8 27.3 20.5 ...
##  $ insecticida     : chr [1:750] "No" "Si" "Si" "No" ...
##  $ plaga           : chr [1:750] "Si" "Si" "No" "No" ...
##  $ acidez          : num [1:750] 0.84 1.01 1.17 0.86 1.11 0.84 1.01 0.86 1.01 1.14 ...
##  $ contenido_brix  : num [1:750] 11.4 10.6 10.1 10.3 11.7 ...
# Clasificación
numericas <- names(datos)[sapply(datos, is.numeric)]
categoricas <- names(datos)[sapply(datos, function(x) is.character(x) || is.factor(x))]

cat("Variables numéricas:\n")
## Variables numéricas:
print(numericas)
##  [1] "id"               "peso_antes"       "diametro_antes"   "peso_despues"    
##  [5] "diametro_despues" "color_nivel"      "danio_nivel"      "humedad_suelo"   
##  [9] "acidez"           "contenido_brix"
cat("\nVariables categóricas:\n")
## 
## Variables categóricas:
print(categoricas)
## [1] "variedad"     "color_desc"   "madurez"      "danio_desc"   "fertilizante"
## [6] "insecticida"  "plaga"

Tenemos 10 variables numericas ( “id”, “peso_antes”, “diametro_antes”, “peso_despues”, “diametro_despues”, “color_nivel”, “danio_nivel”, “humedad_suelo”, “acidez”, “contenido_brix”) 7 variables categóricas (“variedad”, “color_desc”, “madurez”, “danio_desc”, “fertilizante”, “insecticida”, “plaga”).

1.c Resumen estadístico de variables numéricas

summary(select(datos, peso_antes, peso_despues, diametro_antes, diametro_despues, humedad_suelo, acidez, contenido_brix))
##    peso_antes     peso_despues   diametro_antes  diametro_despues
##  Min.   :105.0   Min.   :113.2   Min.   :46.10   Min.   :51.20   
##  1st Qu.:140.7   1st Qu.:143.3   1st Qu.:54.00   1st Qu.:60.60   
##  Median :158.9   Median :156.1   Median :56.30   Median :63.80   
##  Mean   :156.6   Mean   :157.2   Mean   :57.50   Mean   :64.46   
##  3rd Qu.:172.0   3rd Qu.:171.6   3rd Qu.:59.88   3rd Qu.:68.08   
##  Max.   :201.4   Max.   :210.3   Max.   :73.50   Max.   :77.90   
##  humedad_suelo       acidez       contenido_brix 
##  Min.   :15.10   Min.   :0.6000   Min.   : 8.02  
##  1st Qu.:20.30   1st Qu.:0.9025   1st Qu.: 9.82  
##  Median :25.25   Median :1.0500   Median :10.69  
##  Mean   :25.23   Mean   :1.0362   Mean   :10.61  
##  3rd Qu.:30.10   3rd Qu.:1.1700   3rd Qu.:11.53  
##  Max.   :35.00   Max.   :1.4000   Max.   :13.00

1.d Gráficos: histogramas y boxplots

`

# Variables y colores definidos
variables <- c("peso_antes", "peso_despues", "diametro_antes", "diametro_despues",
               "humedad_suelo", "acidez", "contenido_brix")

colores <- c("lightskyblue", "lightcoral", "lightgreen", "plum", "khaki", "lightpink", "lightgray")

# Configuramos el layout: 7 filas × 2 columnas (histograma + boxplot por variable)
par(mfrow = c(7, 2), mar = c(4, 4, 3, 1))  # márgenes ajustados

# Loop para graficar ambos gráficos por variable
for (i in seq_along(variables)) {
  var <- variables[i]
  col <- colores[i]
  
  # Histograma
  hist(datos[[var]],
       main = paste("Histograma de", var),
       xlab = var,
       col = col,
       border = "black")
  
  # Boxplot
  boxplot(datos[[var]],
          main = paste("Boxplot de", var),
          ylab = var,
          col = col)
}

2. Prueba de hipótesis para una media (contenido Brix > 10)

Dado que la empresa considera que un contenido de azúcar superior a 10 grados Brix es necesario para garantizar un sabor aceptable, se desea evaluar si, en promedio, las muestras analizadas cumplen con este umbral mínimo.

Por lo tanto, se formulan las siguientes hipótesis estadísticas:

Hipótesis nula (H₀): la media del contenido de Brix es menor o igual a 10 grados. H0: mu <= 10

Hipótesis alternativa (H₁): la media del contenido de Brix es mayor a 10 grados. H1: mu > 10

Esta es una prueba unilateral superior, ya que nos interesa saber si el contenido medio supera el valor de referencia propuesto por la empresa.

# Media observada
mean(datos$contenido_brix, na.rm = TRUE)
## [1] 10.60652
# Prueba de normalidad
shapiro <- shapiro.test(datos$contenido_brix)

# Prueba t o Wilcoxon según normalidad
if (shapiro$p.value > 0.05) {
  prueba <- t.test(datos$contenido_brix, mu = 10, alternative = "greater")
} else {
  prueba <- wilcox.test(datos$contenido_brix, mu = 10, alternative = "greater")
}
prueba
## 
##  Wilcoxon signed rank test with continuity correction
## 
## data:  datos$contenido_brix
## V = 210672, p-value < 2.2e-16
## alternative hypothesis: true location is greater than 10

Interpretación:

La media observada del contenido de Brix fue de 10.61, un valor levemente superior al umbral mínimo establecido por la empresa (10 grados Brix). Para evaluar si esta diferencia es estadísticamente significativa, se aplicó una prueba de hipótesis. Para verificar si el contenido de Brix sigue una distribución normal, se aplicó la prueba de Shapiro-Wilk sobre la variable contenido_brix. El resultado fue un p-valor extremadamente bajo (p < 2.2 × 10⁻¹⁶), lo que indica que los datos no siguen una distribución normal. Este resultado se complementó visualmente mediante histogramas y gráficos de caja, donde se observó una ligera asimetría y la presencia de valores atípicos. En consecuencia, no se cumplen los supuestos de normalidad requeridos para una prueba t para una muestra. Dado que los datos no presentan una distribución normal, se optó por aplicar una prueba no paramétrica de Wilcoxon para una muestra (Wilcoxon signed rank test). Esta prueba no requiere supuestos de normalidad y evalúa si la mediana de una población difiere significativamente de un valor específico. En este caso, se utilizó para determinar si el contenido de Brix es significativamente mayor a 10 grados. El resultado de la prueba Wilcoxon arrojó un p-valor < 2.2 × 10⁻¹⁶, lo que indica una diferencia estadísticamente significativa respecto al umbral planteado por la empresa. Por lo tanto, se rechaza la hipótesis nula en favor de la alternativa: el contenido medio de azúcar (mediana) es significativamente mayor a 10 grados Brix.

OPcional:

library(dplyr)

# Calcular medias por variedad y marcar si cumplen el umbral
medias_variedades <- datos %>%
  group_by(variedad) %>%
  summarise(media_brix = mean(contenido_brix, na.rm = TRUE)) %>%
  mutate(cumple_umbral = ifelse(media_brix > 10, "Sí", "No"))

# Mostrar la tabla resumen con formato legible
print(medias_variedades)
## # A tibble: 5 × 3
##   variedad   media_brix cumple_umbral
##   <chr>           <dbl> <chr>        
## 1 Clemenules      11.0  Sí           
## 2 Criolla         11.0  Sí           
## 3 Marisol         10.1  Sí           
## 4 Nova            12.0  Sí           
## 5 Okitsu           8.96 No
# Detectar variedades que no cumplen el umbral
variedades_no_cumplen <- medias_variedades %>%
  filter(cumple_umbral == "No") %>%
  pull(variedad)

if(length(variedades_no_cumplen) > 0) {
  cat("\nLas siguientes variedades no superan el umbral de 10 grados Brix (media):\n")
  print(variedades_no_cumplen)
  
  # Filtrar datos excluyendo estas variedades para análisis posterior
  datos_filtrados <- datos %>%
    filter(!variedad %in% variedades_no_cumplen)
  
  cat("\nSe realizará el análisis posterior excluyendo estas variedades.\n")
} else {
  cat("\nTodas las variedades superan el umbral de 10 grados Brix (media).\n")
  datos_filtrados <- datos
}
## 
## Las siguientes variedades no superan el umbral de 10 grados Brix (media):
## [1] "Okitsu"
## 
## Se realizará el análisis posterior excluyendo estas variedades.
library(dplyr)
library(ggplot2)

# 1. Verificamos las variedades en datos_filtrados (Okitsu debe estar excluida)
cat("Variedades consideradas en el análisis:\n")
## Variedades consideradas en el análisis:
print(unique(datos_filtrados$variedad))
## [1] "Clemenules" "Marisol"    "Criolla"    "Nova"
# 2. Calcular y mostrar la media general de contenido Brix (sin Okitsu)
media_filtrada <- mean(datos_filtrados$contenido_brix, na.rm = TRUE)
cat("\nMedia de contenido Brix (excluyendo Okitsu): ", round(media_filtrada, 3), "\n")
## 
## Media de contenido Brix (excluyendo Okitsu):  11.019
print (media_filtrada)
## [1] 11.01873
# 3. Comprobar normalidad con test de Shapiro-Wilk
shapiro_result <- shapiro.test(datos_filtrados$contenido_brix)
cat("\nResultado del test de Shapiro-Wilk:\n")
## 
## Resultado del test de Shapiro-Wilk:
print(shapiro_result)
## 
##  Shapiro-Wilk normality test
## 
## data:  datos_filtrados$contenido_brix
## W = 0.98958, p-value = 0.0002926
# 4. Visualización: histograma y QQ-plot
ggplot(datos_filtrados, aes(x = contenido_brix)) +
  geom_histogram(color = "black", fill = "lightblue", bins = 15) +
  labs(title = "Histograma de grados Brix (sin Okitsu)",
       x = "Contenido de Brix", y = "Frecuencia")

ggplot(datos_filtrados, aes(sample = contenido_brix)) +
  stat_qq() +
  stat_qq_line() +
  labs(title = "QQ-plot de contenido Brix (sin Okitsu)")

# 5. Test según normalidad
if (shapiro_result$p.value > 0.05) {
  cat("\nDistribución normal. Se realiza test t de una muestra:\n")
  test_result <- t.test(datos_filtrados$contenido_brix, mu = 10, alternative = "greater")
} else {
  cat("\nDistribución no normal. Se realiza test de Wilcoxon de una muestra:\n")
  test_result <- wilcox.test(datos_filtrados$contenido_brix, mu = 10, alternative = "greater")
}
## 
## Distribución no normal. Se realiza test de Wilcoxon de una muestra:
# 6. Mostrar resultados del test elegido
print(test_result)
## 
##  Wilcoxon signed rank test with continuity correction
## 
## data:  datos_filtrados$contenido_brix
## V = 167447, p-value < 2.2e-16
## alternative hypothesis: true location is greater than 10

Los datos, excluidos los de la variedad Okitsu, tienen una media de 11.019. Tampoco son normales, se uso una prueba de Sahapiro-Wilk que esta vez dio un p valor < 2.2e-16, por lo que se puede decir que es un valor significativamente mayor que 10.