# ============================================================
# ANÁLISIS FINAL EN RSTUDIO
# Proyecto: Café Castillo - Finca El Guayabo
# Especialización en Estadística
# Estudiante: Nina María Sánchez Ramírez
# Asesora: Dayana Ibeth Castro Guevara
#
# Archivos:
# 1. Resultados_Cafe_2026_4-1.xlsx
# 2. Resultados_Cafe_2026_micro.xlsx
#
# Propósito:
# Contrastar y complementar los resultados obtenidos en SPSS:
# - Muestreo
# - Descriptivos
# - Comparación antes y después de lluvia
# - Análisis bivariado
# - Correlaciones exploratorias
# - Regresión logística binaria
# - Serie temporal por hora de toma con Micro:bit
# - Gráficos llamativos
# - Interpretaciones, conclusiones y recomendaciones
# ============================================================


# ============================================================
# 1. INSTALACION Y CARGUE DE PAQUETES
# ============================================================

paquetes <- c(
  "readxl", "dplyr", "tidyr", "janitor", "ggplot2",
  "broom", "openxlsx", "scales"
)

paquetes_no_instalados <- paquetes[!(paquetes %in% installed.packages()[, "Package"])]

if(length(paquetes_no_instalados) > 0){
  install.packages(paquetes_no_instalados)
}

library(readxl)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyr)
library(janitor)
## 
## Adjuntando el paquete: 'janitor'
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(ggplot2)
library(broom)
library(openxlsx)
library(scales)


# ============================================================
# 2. RUTAS DE LOS ARCHIVOS
# ============================================================

ruta_4en1 <- "C:\\Users\\Nina Sanchez\\Documents\\ACER -LENOVO-NINA 2019-20\\1. USCO\\ESTADISTICA\\2026_Estadistica\\tesis\\Resultados_Cafe_2026_4-1.xlsx"

ruta_micro <- "C:\\Users\\Nina Sanchez\\Documents\\ACER -LENOVO-NINA 2019-20\\1. USCO\\ESTADISTICA\\2026_Estadistica\\tesis\\Resultados_Cafe_2026_micro.xlsx"


# ============================================================
# 3. CREAR CARPETAS DE RESULTADOS
# ============================================================

dir.create("resultados_cafe_rstudio", showWarnings = FALSE)
dir.create("resultados_cafe_rstudio/graficos", showWarnings = FALSE)
dir.create("resultados_cafe_rstudio/tablas", showWarnings = FALSE)


# ============================================================
# 4. CARGAR BASES
# ============================================================

hojas_4en1 <- excel_sheets(ruta_4en1)
hojas_micro <- excel_sheets(ruta_micro)

cat("\n============================================================\n")
## 
## ============================================================
cat("HOJAS DETECTADAS\n")
## HOJAS DETECTADAS
cat("============================================================\n")
## ============================================================
cat("\nArchivo 4 en 1:\n")
## 
## Archivo 4 en 1:
print(hojas_4en1)
## [1] "4-1"
cat("\nArchivo Micro:bit:\n")
## 
## Archivo Micro:bit:
print(hojas_micro)
## [1] "microbit"
hoja_4en1 <- ifelse("4-1" %in% hojas_4en1, "4-1", hojas_4en1[1])
hoja_micro <- ifelse("microbit" %in% hojas_micro, "microbit", hojas_micro[1])

base_4en1 <- read_excel(ruta_4en1, sheet = hoja_4en1) %>%
  clean_names()

base_micro <- read_excel(ruta_micro, sheet = hoja_micro) %>%
  clean_names()

cat("\n============================================================\n")
## 
## ============================================================
cat("NOMBRES DE VARIABLES DESPUÉS DE clean_names()\n")
## NOMBRES DE VARIABLES DESPUÉS DE clean_names()
cat("============================================================\n")
## ============================================================
cat("\nBase 4 en 1:\n")
## 
## Base 4 en 1:
print(names(base_4en1))
##  [1] "no_planta"        "altura_cm"        "temp_sin_lluvia"  "temp_post_lluvia"
##  [5] "p_h_sin_lluvia"   "p_h_post_lluvia"  "hum_sin_lluvia"   "hum_post_lluvia" 
##  [9] "luz_sin_lluvia"   "luz_post_lluvia"  "cond_planta"      "color_hojas"     
## [13] "follaje"          "vigor_tallo"      "flor"             "fruto"
cat("\nBase Micro:bit:\n")
## 
## Base Micro:bit:
print(names(base_micro))
## [1] "no"                             "hora_toma"                     
## [3] "tiempo_min"                     "hum_zona_inclinada_zona_baja"  
## [5] "hum_zona_alta_poca_inclinacion" "clima"
# ============================================================
# 5. AJUSTE DE NOMBRES
# ============================================================

# clean_names() suele convertir pH en p_h.
# Esta sección estandariza los nombres para evitar errores.

if("p_h_sin_lluvia" %in% names(base_4en1)){
  base_4en1 <- base_4en1 %>%
    rename(ph_sin_lluvia = p_h_sin_lluvia)
}

if("p_h_post_lluvia" %in% names(base_4en1)){
  base_4en1 <- base_4en1 %>%
    rename(ph_post_lluvia = p_h_post_lluvia)
}

cat("\n============================================================\n")
## 
## ============================================================
cat("NOMBRES AJUSTADOS\n")
## NOMBRES AJUSTADOS
cat("============================================================\n")
## ============================================================
print(names(base_4en1))
##  [1] "no_planta"        "altura_cm"        "temp_sin_lluvia"  "temp_post_lluvia"
##  [5] "ph_sin_lluvia"    "ph_post_lluvia"   "hum_sin_lluvia"   "hum_post_lluvia" 
##  [9] "luz_sin_lluvia"   "luz_post_lluvia"  "cond_planta"      "color_hojas"     
## [13] "follaje"          "vigor_tallo"      "flor"             "fruto"
print(names(base_micro))
## [1] "no"                             "hora_toma"                     
## [3] "tiempo_min"                     "hum_zona_inclinada_zona_baja"  
## [5] "hum_zona_alta_poca_inclinacion" "clima"
# ============================================================
# 6. RECODIFICACIÓN DE VARIABLES
# ============================================================

# Fruto en tres categorías:
# No visible, Visible, Abundante
# Se conserva para gráficos descriptivos.

base_4en1 <- base_4en1 %>%
  mutate(
    fruto_texto = tolower(trimws(as.character(fruto))),
    fruto_3cat = case_when(
      fruto_texto %in% c("no visible", "no", "sin fruto", "0") ~ "No visible",
      fruto_texto %in% c("visible", "poco") ~ "Visible",
      fruto_texto %in% c("abundante") ~ "Abundante",
      TRUE ~ NA_character_
    ),
    fruto_3cat = factor(
      fruto_3cat,
      levels = c("No visible", "Visible", "Abundante")
    )
  )

# Fruto binario:
# 0 = No visible
# 1 = Visible o Abundante
# Esta variable se usa para regresión logística.

base_4en1 <- base_4en1 %>%
  mutate(
    fruto_bin = case_when(
      fruto_3cat == "No visible" ~ 0,
      fruto_3cat %in% c("Visible", "Abundante") ~ 1,
      TRUE ~ NA_real_
    )
  )

# Flor:
# 0 = Ausente
# 1 = Presente

base_4en1 <- base_4en1 %>%
  mutate(
    flor_texto = tolower(trimws(as.character(flor))),
    flor_a = case_when(
      flor_texto %in% c("ausente", "no", "0") ~ 0,
      flor_texto %in% c("presente", "si", "sí", "1") ~ 1,
      TRUE ~ NA_real_
    )
  )

# Humedad posterior:
# 0 = NOR_normal
# 1 = WET_humectante

base_4en1 <- base_4en1 %>%
  mutate(
    hum_post_texto = tolower(trimws(as.character(hum_post_lluvia))),
    hum_post_a = case_when(
      grepl("nor|normal|0", hum_post_texto) ~ 0,
      grepl("wet|humectante|humedo|húmedo|1", hum_post_texto) ~ 1,
      TRUE ~ NA_real_
    )
  )

# Vigor del tallo:
# 1 = Medio
# 2 = Bueno
# 3 = Muy bueno

base_4en1 <- base_4en1 %>%
  mutate(
    vigor_texto = tolower(trimws(as.character(vigor_tallo))),
    vigor_tallo_a = case_when(
      grepl("medio|1", vigor_texto) ~ 1,
      grepl("muy bueno|3", vigor_texto) ~ 3,
      grepl("bueno|2", vigor_texto) ~ 2,
      TRUE ~ NA_real_
    ),
    vigor_tallo_cat = factor(
      vigor_tallo_a,
      levels = c(1, 2, 3),
      labels = c("Medio", "Bueno", "Muy bueno")
    )
  )

# Clima Micro:bit:
# 0 = Sin lluvia
# 1 = Con lluvia

base_micro <- base_micro %>%
  mutate(
    clima_texto = tolower(trimws(as.character(clima))),
    clima_a = case_when(
      grepl("sin", clima_texto) ~ 0,
      grepl("con", clima_texto) ~ 1,
      TRUE ~ NA_real_
    ),
    clima_cat = factor(
      clima_a,
      levels = c(0, 1),
      labels = c("Sin lluvia", "Con lluvia")
    )
  )


# ============================================================
# 7. CONVERSIÓN DE VARIABLES NUMÉRICAS
# ============================================================

variables_numericas_4en1 <- c(
  "altura_cm", "temp_sin_lluvia", "temp_post_lluvia",
  "ph_sin_lluvia", "ph_post_lluvia",
  "fruto_bin", "flor_a", "hum_post_a", "vigor_tallo_a"
)

for(v in variables_numericas_4en1){
  if(v %in% names(base_4en1)){
    base_4en1[[v]] <- as.numeric(base_4en1[[v]])
  }
}

variables_numericas_micro <- c(
  "tiempo_min",
  "hum_zona_inclinada_zona_baja",
  "hum_zona_alta_poca_inclinacion",
  "clima_a"
)

for(v in variables_numericas_micro){
  if(v %in% names(base_micro)){
    base_micro[[v]] <- as.numeric(base_micro[[v]])
  }
}


# ============================================================
# 8. LIMPIEZA DE HORA_TOMA PARA SERIE TEMPORAL HORARIA
# ============================================================

# La base contiene Hora_Toma, no semana ni fecha.
# Por tanto, se trabaja serie temporal por hora de toma.

if("hora_toma" %in% names(base_micro)){
  
  base_micro <- base_micro %>%
    mutate(
      hora_toma_original = as.character(hora_toma),
      hora_toma_limpia = tolower(trimws(hora_toma_original)),
      hora_toma_limpia = gsub("\\.", "", hora_toma_limpia),
      hora_toma_limpia = gsub("a m", "AM", hora_toma_limpia),
      hora_toma_limpia = gsub("p m", "PM", hora_toma_limpia),
      hora_toma_limpia = gsub("am", "AM", hora_toma_limpia),
      hora_toma_limpia = gsub("pm", "PM", hora_toma_limpia),
      hora_toma_formato = as.POSIXct(
        hora_toma_limpia,
        format = "%I:%M %p",
        tz = "America/Bogota"
      )
    )
  
} else {
  
  base_micro <- base_micro %>%
    mutate(
      hora_toma_original = NA_character_,
      hora_toma_limpia = NA_character_,
      hora_toma_formato = as.POSIXct(NA)
    )
}

# Eliminar registros vacíos en Micro:bit
base_micro <- base_micro %>%
  filter(
    !is.na(tiempo_min),
    !is.na(hum_zona_inclinada_zona_baja),
    !is.na(hum_zona_alta_poca_inclinacion)
  )


# ============================================================
# 9. VALIDACIÓN DE BASES
# ============================================================

cat("\n============================================================\n")
## 
## ============================================================
cat("VALIDACIÓN GENERAL\n")
## VALIDACIÓN GENERAL
cat("============================================================\n")
## ============================================================
cat("\nBase 4 en 1\n")
## 
## Base 4 en 1
cat("Filas:", nrow(base_4en1), "\n")
## Filas: 28
cat("Columnas:", ncol(base_4en1), "\n")
## Columnas: 26
print(colSums(is.na(base_4en1)))
##        no_planta        altura_cm  temp_sin_lluvia temp_post_lluvia 
##                0                0                0                0 
##    ph_sin_lluvia   ph_post_lluvia   hum_sin_lluvia  hum_post_lluvia 
##                0                0                0                0 
##   luz_sin_lluvia  luz_post_lluvia      cond_planta      color_hojas 
##                0                0                0                0 
##          follaje      vigor_tallo             flor            fruto 
##                0                0                0                0 
##      fruto_texto       fruto_3cat        fruto_bin       flor_texto 
##                0                0                0                0 
##           flor_a   hum_post_texto       hum_post_a      vigor_texto 
##                0                0                0                0 
##    vigor_tallo_a  vigor_tallo_cat 
##                0                0
cat("\nBase Micro:bit\n")
## 
## Base Micro:bit
cat("Filas:", nrow(base_micro), "\n")
## Filas: 72
cat("Columnas:", ncol(base_micro), "\n")
## Columnas: 12
print(colSums(is.na(base_micro)))
##                             no                      hora_toma 
##                              0                              0 
##                     tiempo_min   hum_zona_inclinada_zona_baja 
##                              0                              0 
## hum_zona_alta_poca_inclinacion                          clima 
##                              0                              0 
##                    clima_texto                        clima_a 
##                              0                              0 
##                      clima_cat             hora_toma_original 
##                              0                              0 
##               hora_toma_limpia              hora_toma_formato 
##                              0                             72
cat("\nTabla de control Fruto original vs Fruto binario:\n")
## 
## Tabla de control Fruto original vs Fruto binario:
print(table(base_4en1$fruto, base_4en1$fruto_bin, useNA = "ifany"))
##             
##               0  1
##   Abundante   0  5
##   No Visible 17  0
##   Visible     0  6
cat("\nFrecuencia fruto en tres categorías:\n")
## 
## Frecuencia fruto en tres categorías:
print(tabyl(base_4en1, fruto_3cat))
##  fruto_3cat  n   percent
##  No visible 17 0.6071429
##     Visible  6 0.2142857
##   Abundante  5 0.1785714
cat("\nFrecuencia fruto binario:\n")
## 
## Frecuencia fruto binario:
print(tabyl(base_4en1, fruto_bin))
##  fruto_bin  n   percent
##          0 17 0.6071429
##          1 11 0.3928571
# ============================================================
# 10. CONTEXTO Y MUESTREO
# ============================================================

poblacion_lote <- 200
muestra_4en1 <- nrow(base_4en1)
muestra_micro <- nrow(base_micro)
fraccion_muestreo <- muestra_4en1 / poblacion_lote

muestreo_resumen <- data.frame(
  componente = c(
    "Población aproximada del lote",
    "Plantas evaluadas con equipo 4 en 1",
    "Registros temporales Micro:bit",
    "Fracción de muestreo base 4 en 1"
  ),
  valor = c(
    poblacion_lote,
    muestra_4en1,
    muestra_micro,
    round(fraccion_muestreo, 3)
  )
)

cat("\n============================================================\n")
## 
## ============================================================
cat("CONTEXTO Y MUESTREO\n")
## CONTEXTO Y MUESTREO
cat("============================================================\n")
## ============================================================
print(muestreo_resumen)
##                            componente  valor
## 1       Población aproximada del lote 200.00
## 2 Plantas evaluadas con equipo 4 en 1  28.00
## 3      Registros temporales Micro:bit  72.00
## 4    Fracción de muestreo base 4 en 1   0.14
cat("\nInterpretación:\n")
## 
## Interpretación:
cat("El estudio se desarrolla en un lote aproximado de 200 plantas de café variedad Castillo.\n")
## El estudio se desarrolla en un lote aproximado de 200 plantas de café variedad Castillo.
cat("La base 4 en 1 corresponde a 28 plantas evaluadas mediante muestreo no probabilístico por conveniencia.\n")
## La base 4 en 1 corresponde a 28 plantas evaluadas mediante muestreo no probabilístico por conveniencia.
cat("La base Micro:bit corresponde a registros temporales de humedad del suelo, no a plantas individuales.\n")
## La base Micro:bit corresponde a registros temporales de humedad del suelo, no a plantas individuales.
cat("Por esta razón, las dos bases se analizan de forma complementaria y no se fusionan directamente.\n")
## Por esta razón, las dos bases se analizan de forma complementaria y no se fusionan directamente.
# ============================================================
# 11. DESCRIPTIVOS BASE 4 EN 1
# ============================================================

descriptivos_4en1 <- base_4en1 %>%
  summarise(
    n = n(),
    
    altura_min = min(altura_cm, na.rm = TRUE),
    altura_max = max(altura_cm, na.rm = TRUE),
    altura_media = mean(altura_cm, na.rm = TRUE),
    altura_de = sd(altura_cm, na.rm = TRUE),
    
    temp_sin_min = min(temp_sin_lluvia, na.rm = TRUE),
    temp_sin_max = max(temp_sin_lluvia, na.rm = TRUE),
    temp_sin_media = mean(temp_sin_lluvia, na.rm = TRUE),
    temp_sin_de = sd(temp_sin_lluvia, na.rm = TRUE),
    
    temp_post_min = min(temp_post_lluvia, na.rm = TRUE),
    temp_post_max = max(temp_post_lluvia, na.rm = TRUE),
    temp_post_media = mean(temp_post_lluvia, na.rm = TRUE),
    temp_post_de = sd(temp_post_lluvia, na.rm = TRUE),
    
    ph_sin_min = min(ph_sin_lluvia, na.rm = TRUE),
    ph_sin_max = max(ph_sin_lluvia, na.rm = TRUE),
    ph_sin_media = mean(ph_sin_lluvia, na.rm = TRUE),
    ph_sin_de = sd(ph_sin_lluvia, na.rm = TRUE),
    
    ph_post_min = min(ph_post_lluvia, na.rm = TRUE),
    ph_post_max = max(ph_post_lluvia, na.rm = TRUE),
    ph_post_media = mean(ph_post_lluvia, na.rm = TRUE),
    ph_post_de = sd(ph_post_lluvia, na.rm = TRUE)
  )

cat("\n============================================================\n")
## 
## ============================================================
cat("DESCRIPTIVOS BASE 4 EN 1\n")
## DESCRIPTIVOS BASE 4 EN 1
cat("============================================================\n")
## ============================================================
print(descriptivos_4en1)
## # A tibble: 1 × 21
##       n altura_min altura_max altura_media altura_de temp_sin_min temp_sin_max
##   <int>      <dbl>      <dbl>        <dbl>     <dbl>        <dbl>        <dbl>
## 1    28        115        158         137.      9.81           24           29
## # ℹ 14 more variables: temp_sin_media <dbl>, temp_sin_de <dbl>,
## #   temp_post_min <dbl>, temp_post_max <dbl>, temp_post_media <dbl>,
## #   temp_post_de <dbl>, ph_sin_min <dbl>, ph_sin_max <dbl>, ph_sin_media <dbl>,
## #   ph_sin_de <dbl>, ph_post_min <dbl>, ph_post_max <dbl>, ph_post_media <dbl>,
## #   ph_post_de <dbl>
# ============================================================
# 12. FRECUENCIAS AGRONÓMICAS
# ============================================================

frecuencia_fruto_3cat <- base_4en1 %>%
  tabyl(fruto_3cat) %>%
  adorn_pct_formatting(digits = 1)

frecuencia_fruto <- base_4en1 %>%
  tabyl(fruto_bin) %>%
  adorn_pct_formatting(digits = 1)

frecuencia_flor <- base_4en1 %>%
  tabyl(flor_a) %>%
  adorn_pct_formatting(digits = 1)

frecuencia_humedad_post <- base_4en1 %>%
  tabyl(hum_post_a) %>%
  adorn_pct_formatting(digits = 1)

frecuencia_vigor <- base_4en1 %>%
  tabyl(vigor_tallo_cat) %>%
  adorn_pct_formatting(digits = 1)

cat("\n============================================================\n")
## 
## ============================================================
cat("FRECUENCIAS AGRONÓMICAS\n")
## FRECUENCIAS AGRONÓMICAS
cat("============================================================\n")
## ============================================================
print(frecuencia_fruto_3cat)
##  fruto_3cat  n percent
##  No visible 17   60.7%
##     Visible  6   21.4%
##   Abundante  5   17.9%
print(frecuencia_fruto)
##  fruto_bin  n percent
##          0 17   60.7%
##          1 11   39.3%
print(frecuencia_flor)
##  flor_a  n percent
##       0 25   89.3%
##       1  3   10.7%
print(frecuencia_humedad_post)
##  hum_post_a  n percent
##           0  8   28.6%
##           1 20   71.4%
print(frecuencia_vigor)
##  vigor_tallo_cat  n percent
##            Medio  4   14.3%
##            Bueno 18   64.3%
##        Muy bueno  6   21.4%
# ============================================================
# 13. COMPARACIÓN ANTES Y DESPUÉS DE LA LLUVIA
# ============================================================

comparacion_antes_despues <- base_4en1 %>%
  summarise(
    temp_sin_media = mean(temp_sin_lluvia, na.rm = TRUE),
    temp_post_media = mean(temp_post_lluvia, na.rm = TRUE),
    diferencia_temp = temp_post_media - temp_sin_media,
    
    ph_sin_media = mean(ph_sin_lluvia, na.rm = TRUE),
    ph_post_media = mean(ph_post_lluvia, na.rm = TRUE),
    diferencia_ph = ph_post_media - ph_sin_media
  )

prueba_temp_pareada <- t.test(
  base_4en1$temp_sin_lluvia,
  base_4en1$temp_post_lluvia,
  paired = TRUE
)

prueba_ph_pareada <- t.test(
  base_4en1$ph_sin_lluvia,
  base_4en1$ph_post_lluvia,
  paired = TRUE
)

cat("\n============================================================\n")
## 
## ============================================================
cat("ANTES VS DESPUÉS DE LA LLUVIA\n")
## ANTES VS DESPUÉS DE LA LLUVIA
cat("============================================================\n")
## ============================================================
print(comparacion_antes_despues)
## # A tibble: 1 × 6
##   temp_sin_media temp_post_media diferencia_temp ph_sin_media ph_post_media
##            <dbl>           <dbl>           <dbl>        <dbl>         <dbl>
## 1           26.2            20.2           -5.96         6.41          5.04
## # ℹ 1 more variable: diferencia_ph <dbl>
print(prueba_temp_pareada)
## 
##  Paired t-test
## 
## data:  base_4en1$temp_sin_lluvia and base_4en1$temp_post_lluvia
## t = 21.356, df = 27, p-value < 2.2e-16
## alternative hypothesis: true mean difference is not equal to 0
## 95 percent confidence interval:
##  5.391259 6.537313
## sample estimates:
## mean difference 
##        5.964286
print(prueba_ph_pareada)
## 
##  Paired t-test
## 
## data:  base_4en1$ph_sin_lluvia and base_4en1$ph_post_lluvia
## t = 9.2204, df = 27, p-value = 7.865e-10
## alternative hypothesis: true mean difference is not equal to 0
## 95 percent confidence interval:
##  1.069017 1.680983
## sample estimates:
## mean difference 
##           1.375
# ============================================================
# 14. ANÁLISIS BIVARIADO CATEGÓRICO
# ============================================================

tabla_flor_fruto <- table(
  Fruto = base_4en1$fruto_bin,
  Flor = base_4en1$flor_a
)

tabla_hum_fruto <- table(
  Fruto = base_4en1$fruto_bin,
  Humedad_post = base_4en1$hum_post_a
)

tabla_vigor_fruto <- table(
  Fruto = base_4en1$fruto_bin,
  Vigor = base_4en1$vigor_tallo_a
)

chi_flor <- suppressWarnings(chisq.test(tabla_flor_fruto))
chi_hum <- suppressWarnings(chisq.test(tabla_hum_fruto))
chi_vigor <- suppressWarnings(chisq.test(tabla_vigor_fruto))

fisher_flor <- fisher.test(tabla_flor_fruto)
fisher_hum <- fisher.test(tabla_hum_fruto)

resumen_chi <- data.frame(
  relacion = c(
    "Fruto visible x Flor",
    "Fruto visible x Humedad posterior",
    "Fruto visible x Vigor del tallo"
  ),
  chi_cuadrado = c(
    as.numeric(chi_flor$statistic),
    as.numeric(chi_hum$statistic),
    as.numeric(chi_vigor$statistic)
  ),
  gl = c(
    as.numeric(chi_flor$parameter),
    as.numeric(chi_hum$parameter),
    as.numeric(chi_vigor$parameter)
  ),
  p_chi = c(
    chi_flor$p.value,
    chi_hum$p.value,
    chi_vigor$p.value
  ),
  p_fisher = c(
    fisher_flor$p.value,
    fisher_hum$p.value,
    NA
  )
)

cat("\n============================================================\n")
## 
## ============================================================
cat("ANÁLISIS BIVARIADO CATEGÓRICO\n")
## ANÁLISIS BIVARIADO CATEGÓRICO
cat("============================================================\n")
## ============================================================
print(tabla_flor_fruto)
##      Flor
## Fruto  0  1
##     0 14  3
##     1 11  0
print(tabla_hum_fruto)
##      Humedad_post
## Fruto  0  1
##     0  8  9
##     1  0 11
print(tabla_vigor_fruto)
##      Vigor
## Fruto  1  2  3
##     0  4 10  3
##     1  0  8  3
print(resumen_chi)
##                            relacion chi_cuadrado gl      p_chi    p_fisher
## 1              Fruto visible x Flor     0.720713  1 0.39591013 0.257936508
## 2 Fruto visible x Humedad posterior     5.124599  1 0.02358902 0.009679531
## 3   Fruto visible x Vigor del tallo     3.077837  2 0.21461306          NA
# ============================================================
# 15. ANÁLISIS BIVARIADO CONTINUO
# ============================================================

analisis_t <- function(variable){
  
  grupo0 <- base_4en1 %>%
    filter(fruto_bin == 0) %>%
    pull(variable)
  
  grupo1 <- base_4en1 %>%
    filter(fruto_bin == 1) %>%
    pull(variable)
  
  prueba <- t.test(grupo0, grupo1, var.equal = TRUE)
  
  n0 <- length(na.omit(grupo0))
  n1 <- length(na.omit(grupo1))
  
  media0 <- mean(grupo0, na.rm = TRUE)
  media1 <- mean(grupo1, na.rm = TRUE)
  
  sd0 <- sd(grupo0, na.rm = TRUE)
  sd1 <- sd(grupo1, na.rm = TRUE)
  
  sd_pooled <- sqrt(((n0 - 1) * sd0^2 + (n1 - 1) * sd1^2) / (n0 + n1 - 2))
  d_cohen <- (media0 - media1) / sd_pooled
  
  data.frame(
    variable = variable,
    n_sin_fruto = n0,
    n_con_fruto = n1,
    media_sin_fruto = media0,
    media_con_fruto = media1,
    t = as.numeric(prueba$statistic),
    gl = as.numeric(prueba$parameter),
    p_valor = prueba$p.value,
    d_cohen = d_cohen
  )
}

resumen_t <- bind_rows(
  analisis_t("altura_cm"),
  analisis_t("temp_post_lluvia"),
  analisis_t("ph_post_lluvia"),
  analisis_t("ph_sin_lluvia"),
  analisis_t("temp_sin_lluvia")
)

cat("\n============================================================\n")
## 
## ============================================================
cat("ANÁLISIS BIVARIADO CONTINUO\n")
## ANÁLISIS BIVARIADO CONTINUO
cat("============================================================\n")
## ============================================================
print(resumen_t)
##           variable n_sin_fruto n_con_fruto media_sin_fruto media_con_fruto
## 1        altura_cm          17          11      136.117647      138.636364
## 2 temp_post_lluvia          17          11       20.176471       20.363636
## 3   ph_post_lluvia          17          11        5.205882        4.772727
## 4    ph_sin_lluvia          17          11        6.352941        6.500000
## 5  temp_sin_lluvia          17          11       26.411765       25.909091
##            t gl    p_valor    d_cohen
## 1 -0.6564490 26 0.51730361 -0.2540149
## 2 -0.8213853 26 0.41889524 -0.3178375
## 3  2.6296910 26 0.01416553  1.0175668
## 4 -0.7386711 26 0.46672303 -0.2858310
## 5  1.0098236 26 0.32188587  0.3907542
# ============================================================
# 16. CORRELACIONES EXPLORATORIAS CON FRUTO
# ============================================================

variables_cor <- c(
  "altura_cm", "temp_post_lluvia", "ph_post_lluvia",
  "ph_sin_lluvia", "temp_sin_lluvia", "vigor_tallo_a"
)

correlaciones_fruto <- lapply(variables_cor, function(v){
  
  datos_temp <- base_4en1 %>%
    select(fruto_bin, all_of(v)) %>%
    filter(!is.na(fruto_bin), !is.na(.data[[v]]))
  
  pearson <- cor.test(datos_temp$fruto_bin, datos_temp[[v]], method = "pearson")
  spearman <- suppressWarnings(cor.test(datos_temp$fruto_bin, datos_temp[[v]], method = "spearman"))
  
  data.frame(
    variable = v,
    pearson_r = as.numeric(pearson$estimate),
    pearson_p = pearson$p.value,
    spearman_rho = as.numeric(spearman$estimate),
    spearman_p = spearman$p.value
  )
}) %>%
  bind_rows()

cat("\n============================================================\n")
## 
## ============================================================
cat("CORRELACIONES EXPLORATORIAS CON FRUTO\n")
## CORRELACIONES EXPLORATORIAS CON FRUTO
cat("============================================================\n")
## ============================================================
print(correlaciones_fruto)
##           variable  pearson_r  pearson_p spearman_rho spearman_p
## 1        altura_cm  0.1276864 0.51730361    0.1042943 0.59739061
## 2 temp_post_lluvia  0.1590367 0.41889524    0.1900529 0.33270366
## 3   ph_post_lluvia -0.4583592 0.01416553   -0.4537006 0.01530975
## 4    ph_sin_lluvia  0.1433688 0.46672303    0.2231550 0.25368045
## 5  temp_sin_lluvia -0.1942696 0.32188587   -0.1721601 0.38101985
## 6    vigor_tallo_a  0.2729080 0.15999391    0.2662633 0.17082128
# ============================================================
# 17. MODELO LOGÍSTICO SIMPLE
# ============================================================

modelo_simple <- glm(
  fruto_bin ~ ph_post_lluvia,
  data = base_4en1,
  family = binomial
)

coef_simple <- tidy(modelo_simple) %>%
  mutate(
    odds_ratio = exp(estimate),
    ic_inf = exp(estimate - 1.96 * std.error),
    ic_sup = exp(estimate + 1.96 * std.error)
  )

b0_simple <- coef(modelo_simple)[1]
b1_simple <- coef(modelo_simple)[2]

cat("\n============================================================\n")
## 
## ============================================================
cat("MODELO LOGÍSTICO SIMPLE\n")
## MODELO LOGÍSTICO SIMPLE
cat("============================================================\n")
## ============================================================
print(summary(modelo_simple))
## 
## Call:
## glm(formula = fruto_bin ~ ph_post_lluvia, family = binomial, 
##     data = base_4en1)
## 
## Coefficients:
##                Estimate Std. Error z value Pr(>|z|)  
## (Intercept)      14.693      7.367   1.995   0.0461 *
## ph_post_lluvia   -3.042      1.489  -2.042   0.0411 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 37.521  on 27  degrees of freedom
## Residual deviance: 30.399  on 26  degrees of freedom
## AIC: 34.399
## 
## Number of Fisher Scoring iterations: 5
print(coef_simple)
## # A tibble: 2 × 8
##   term          estimate std.error statistic p.value odds_ratio  ic_inf   ic_sup
##   <chr>            <dbl>     <dbl>     <dbl>   <dbl>      <dbl>   <dbl>    <dbl>
## 1 (Intercept)      14.7       7.37      1.99  0.0461    2.41e+6 1.29    4.49e+12
## 2 ph_post_lluv…    -3.04      1.49     -2.04  0.0411    4.78e-2 0.00258 8.85e- 1
cat("\nEcuación modelo simple:\n")
## 
## Ecuación modelo simple:
cat("logit(p) =", round(b0_simple, 3), "+", round(b1_simple, 3), "*(pH_PostLluvia)\n")
## logit(p) = 14.693 + -3.042 *(pH_PostLluvia)
# ============================================================
# 18. MODELO LOGÍSTICO MÚLTIPLE
# ============================================================

modelo_multiple <- glm(
  fruto_bin ~ altura_cm + ph_post_lluvia + temp_post_lluvia,
  data = base_4en1,
  family = binomial
)

coef_multiple <- tidy(modelo_multiple) %>%
  mutate(
    odds_ratio = exp(estimate),
    ic_inf = exp(estimate - 1.96 * std.error),
    ic_sup = exp(estimate + 1.96 * std.error)
  )

b_multiple <- coef(modelo_multiple)

cat("\n============================================================\n")
## 
## ============================================================
cat("MODELO LOGÍSTICO MÚLTIPLE\n")
## MODELO LOGÍSTICO MÚLTIPLE
cat("============================================================\n")
## ============================================================
print(summary(modelo_multiple))
## 
## Call:
## glm(formula = fruto_bin ~ altura_cm + ph_post_lluvia + temp_post_lluvia, 
##     family = binomial, data = base_4en1)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)  
## (Intercept)       2.27735   20.28724   0.112    0.911  
## altura_cm         0.02325    0.05048   0.461    0.645  
## ph_post_lluvia   -3.01992    1.54747  -1.952    0.051 .
## temp_post_lluvia  0.44787    0.77443   0.578    0.563  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 37.521  on 27  degrees of freedom
## Residual deviance: 29.950  on 24  degrees of freedom
## AIC: 37.95
## 
## Number of Fisher Scoring iterations: 5
print(coef_multiple)
## # A tibble: 4 × 8
##   term          estimate std.error statistic p.value odds_ratio   ic_inf  ic_sup
##   <chr>            <dbl>     <dbl>     <dbl>   <dbl>      <dbl>    <dbl>   <dbl>
## 1 (Intercept)     2.28     20.3        0.112  0.911      9.75   5.25e-17 1.81e18
## 2 altura_cm       0.0233    0.0505     0.461  0.645      1.02   9.27e- 1 1.13e 0
## 3 ph_post_lluv…  -3.02      1.55      -1.95   0.0510     0.0488 2.35e- 3 1.01e 0
## 4 temp_post_ll…   0.448     0.774      0.578  0.563      1.56   3.43e- 1 7.14e 0
cat("\nEcuación modelo múltiple:\n")
## 
## Ecuación modelo múltiple:
cat(
  "logit(p) =",
  round(b_multiple[1], 3), "+",
  round(b_multiple["altura_cm"], 3), "*(Altura_cm) +",
  round(b_multiple["ph_post_lluvia"], 3), "*(pH_PostLluvia) +",
  round(b_multiple["temp_post_lluvia"], 3), "*(Temp_PostLluvia)\n"
)
## logit(p) = 2.277 + 0.023 *(Altura_cm) + -3.02 *(pH_PostLluvia) + 0.448 *(Temp_PostLluvia)
# ============================================================
# 19. PSEUDO R2
# ============================================================

pseudo_r2 <- function(modelo){
  
  ll_modelo <- as.numeric(logLik(modelo))
  modelo_nulo <- update(modelo, . ~ 1)
  ll_nulo <- as.numeric(logLik(modelo_nulo))
  n <- nobs(modelo)
  
  r2_cox_snell <- 1 - exp((2 / n) * (ll_nulo - ll_modelo))
  r2_nagelkerke <- r2_cox_snell / (1 - exp((2 / n) * ll_nulo))
  
  data.frame(
    r2_cox_snell = r2_cox_snell,
    r2_nagelkerke = r2_nagelkerke
  )
}

r2_simple <- pseudo_r2(modelo_simple)
r2_multiple <- pseudo_r2(modelo_multiple)


# ============================================================
# 20. MATRIZ DE CLASIFICACIÓN
# ============================================================

clasificacion_modelo <- function(modelo, nombre_modelo){
  
  datos_modelo <- model.frame(modelo)
  observado <- datos_modelo[[1]]
  
  probabilidad <- predict(modelo, type = "response")
  predicho <- ifelse(probabilidad >= 0.5, 1, 0)
  
  matriz <- table(
    Observado = factor(observado, levels = c(0, 1)),
    Predicho = factor(predicho, levels = c(0, 1))
  )
  
  tn <- matriz["0", "0"]
  fp <- matriz["0", "1"]
  fn <- matriz["1", "0"]
  tp <- matriz["1", "1"]
  
  exactitud <- (tp + tn) / sum(matriz)
  sensibilidad <- tp / (tp + fn)
  especificidad <- tn / (tn + fp)
  
  resumen <- data.frame(
    modelo = nombre_modelo,
    exactitud = exactitud,
    sensibilidad = sensibilidad,
    especificidad = especificidad
  )
  
  return(list(
    matriz = matriz,
    resumen = resumen
  ))
}

clas_simple <- clasificacion_modelo(modelo_simple, "Simple: pH_PostLluvia")
clas_multiple <- clasificacion_modelo(modelo_multiple, "Múltiple: altura + pH + temperatura")


# ============================================================
# 21. COMPARACIÓN DE MODELOS
# ============================================================

comparacion_modelos <- data.frame(
  modelo = c(
    "Simple: pH_PostLluvia",
    "Múltiple: Altura_cm + pH_PostLluvia + Temp_PostLluvia"
  ),
  menos_2ll = c(
    -2 * as.numeric(logLik(modelo_simple)),
    -2 * as.numeric(logLik(modelo_multiple))
  ),
  parametros = c(
    length(coef(modelo_simple)),
    length(coef(modelo_multiple))
  ),
  aic = c(
    AIC(modelo_simple),
    AIC(modelo_multiple)
  ),
  r2_nagelkerke = c(
    r2_simple$r2_nagelkerke,
    r2_multiple$r2_nagelkerke
  ),
  exactitud = c(
    clas_simple$resumen$exactitud,
    clas_multiple$resumen$exactitud
  ),
  sensibilidad = c(
    clas_simple$resumen$sensibilidad,
    clas_multiple$resumen$sensibilidad
  ),
  especificidad = c(
    clas_simple$resumen$especificidad,
    clas_multiple$resumen$especificidad
  )
)

cat("\n============================================================\n")
## 
## ============================================================
cat("COMPARACIÓN DE MODELOS\n")
## COMPARACIÓN DE MODELOS
cat("============================================================\n")
## ============================================================
print(comparacion_modelos)
##                                                  modelo menos_2ll parametros
## 1                                 Simple: pH_PostLluvia  30.39931          2
## 2 Múltiple: Altura_cm + pH_PostLluvia + Temp_PostLluvia  29.94969          4
##        aic r2_nagelkerke exactitud sensibilidad especificidad
## 1 34.39931     0.3042200 0.6785714    0.3636364     0.8823529
## 2 37.94969     0.3209541 0.6428571    0.3636364     0.8235294
# ============================================================
# 22. PROBABILIDAD ESTIMADA DE FRUTO SEGÚN PH
# ============================================================

rango_ph <- data.frame(
  ph_post_lluvia = seq(
    min(base_4en1$ph_post_lluvia, na.rm = TRUE),
    max(base_4en1$ph_post_lluvia, na.rm = TRUE),
    length.out = 100
  )
)

rango_ph$prob_fruto <- predict(
  modelo_simple,
  newdata = rango_ph,
  type = "response"
)


# ============================================================
# 23. ANÁLISIS MICRO:BIT COMO SERIE TEMPORAL POR HORA
# ============================================================

descriptivos_micro <- base_micro %>%
  summarise(
    n = n(),
    
    tiempo_min_min = min(tiempo_min, na.rm = TRUE),
    tiempo_min_max = max(tiempo_min, na.rm = TRUE),
    tiempo_min_media = mean(tiempo_min, na.rm = TRUE),
    tiempo_min_de = sd(tiempo_min, na.rm = TRUE),
    
    zona_baja_min = min(hum_zona_inclinada_zona_baja, na.rm = TRUE),
    zona_baja_max = max(hum_zona_inclinada_zona_baja, na.rm = TRUE),
    zona_baja_media = mean(hum_zona_inclinada_zona_baja, na.rm = TRUE),
    zona_baja_de = sd(hum_zona_inclinada_zona_baja, na.rm = TRUE),
    
    zona_alta_min = min(hum_zona_alta_poca_inclinacion, na.rm = TRUE),
    zona_alta_max = max(hum_zona_alta_poca_inclinacion, na.rm = TRUE),
    zona_alta_media = mean(hum_zona_alta_poca_inclinacion, na.rm = TRUE),
    zona_alta_de = sd(hum_zona_alta_poca_inclinacion, na.rm = TRUE)
  )

prueba_micro_baja <- t.test(
  hum_zona_inclinada_zona_baja ~ clima_a,
  data = base_micro
)

prueba_micro_alta <- t.test(
  hum_zona_alta_poca_inclinacion ~ clima_a,
  data = base_micro
)

modelo_tiempo_baja <- lm(
  hum_zona_inclinada_zona_baja ~ tiempo_min,
  data = base_micro
)

modelo_tiempo_alta <- lm(
  hum_zona_alta_poca_inclinacion ~ tiempo_min,
  data = base_micro
)

cor_zonas <- cor.test(
  base_micro$hum_zona_inclinada_zona_baja,
  base_micro$hum_zona_alta_poca_inclinacion,
  method = "spearman"
)
## Warning in cor.test.default(base_micro$hum_zona_inclinada_zona_baja,
## base_micro$hum_zona_alta_poca_inclinacion, : cannot compute exact p-value with
## ties
cat("\n============================================================\n")
## 
## ============================================================
cat("MICRO:BIT: SERIE TEMPORAL POR HORA DE TOMA\n")
## MICRO:BIT: SERIE TEMPORAL POR HORA DE TOMA
cat("============================================================\n")
## ============================================================
print(descriptivos_micro)
## # A tibble: 1 × 13
##       n tiempo_min_min tiempo_min_max tiempo_min_media tiempo_min_de
##   <int>          <dbl>          <dbl>            <dbl>         <dbl>
## 1    72             30           2160             1095          628.
## # ℹ 8 more variables: zona_baja_min <dbl>, zona_baja_max <dbl>,
## #   zona_baja_media <dbl>, zona_baja_de <dbl>, zona_alta_min <dbl>,
## #   zona_alta_max <dbl>, zona_alta_media <dbl>, zona_alta_de <dbl>
print(prueba_micro_baja)
## 
##  Welch Two Sample t-test
## 
## data:  hum_zona_inclinada_zona_baja by clima_a
## t = 3.7446, df = 61.556, p-value = 4e-04
## alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
## 95 percent confidence interval:
##   3.142521 10.341831
## sample estimates:
## mean in group 0 mean in group 1 
##        658.1967        651.4545
print(prueba_micro_alta)
## 
##  Welch Two Sample t-test
## 
## data:  hum_zona_alta_poca_inclinacion by clima_a
## t = 3.3836, df = 60.106, p-value = 0.001264
## alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
## 95 percent confidence interval:
##   9.835882 38.280362
## sample estimates:
## mean in group 0 mean in group 1 
##        678.9672        654.9091
print(summary(modelo_tiempo_baja))
## 
## Call:
## lm(formula = hum_zona_inclinada_zona_baja ~ tiempo_min, data = base_micro)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -14.353  -7.614  -1.971   4.918  21.248 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 671.746479   2.411223 278.592  < 2e-16 ***
## tiempo_min   -0.013315   0.001914  -6.958 1.49e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 10.12 on 70 degrees of freedom
## Multiple R-squared:  0.4089, Adjusted R-squared:  0.4004 
## F-statistic: 48.42 on 1 and 70 DF,  p-value: 1.489e-09
print(summary(modelo_tiempo_alta))
## 
## Call:
## lm(formula = hum_zona_alta_poca_inclinacion ~ tiempo_min, data = base_micro)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -113.42  -24.88  -15.22   23.42  189.74 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 655.30282   12.10959  54.114   <2e-16 ***
## tiempo_min    0.01826    0.00961   1.899   0.0616 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 50.84 on 70 degrees of freedom
## Multiple R-squared:  0.04902,    Adjusted R-squared:  0.03543 
## F-statistic: 3.608 on 1 and 70 DF,  p-value: 0.06162
print(cor_zonas)
## 
##  Spearman's rank correlation rho
## 
## data:  base_micro$hum_zona_inclinada_zona_baja and base_micro$hum_zona_alta_poca_inclinacion
## S = 54975, p-value = 0.3315
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##       rho 
## 0.1160989
cat("\nNota metodológica:\n")
## 
## Nota metodológica:
cat("La base Micro:bit tiene Hora_Toma y Tiempo_min, pero no fecha ni semana.\n")
## La base Micro:bit tiene Hora_Toma y Tiempo_min, pero no fecha ni semana.
cat("Por tanto, se analiza una serie temporal por horas del día y por tiempo acumulado,\n")
## Por tanto, se analiza una serie temporal por horas del día y por tiempo acumulado,
cat("no una serie semanal 2026.\n")
## no una serie semanal 2026.
# ============================================================
# 24. GRÁFICOS LLAMATIVOS
# ============================================================

# Paleta de colores
color_verde <- "#2E7D32"
color_naranja <- "#F57C00"
color_azul <- "#1565C0"
color_morado <- "#7B1FA2"
color_rojo <- "#C62828"
color_amarillo <- "#FBC02D"
color_turquesa <- "#00897B"
color_rosado <- "#D81B60"
# Gráfico 1. Fruto en tres categorías
grafico_fruto_3cat <- ggplot(base_4en1, aes(x = fruto_3cat, fill = fruto_3cat)) +
  geom_bar(color = "black", width = 0.7) +
  geom_text(
    stat = "count",
    aes(label = after_stat(count)),
    vjust = -0.4,
    size = 5,
    fontface = "bold"
  ) +
  scale_fill_manual(
    values = c(
      "No visible" = color_rojo,
      "Visible" = color_turquesa,
      "Abundante" = color_amarillo
    )
  ) +
  labs(
    title = "Distribución de fruto observado en plantas de café",
    subtitle = "Base 4 en 1, finca El Guayabo",
    x = "Categoría de fruto",
    y = "Número de plantas",
    fill = "Fruto"
  ) +
  theme_minimal(base_size = 13)

print(grafico_fruto_3cat)

ggsave(
  "resultados_cafe_rstudio/graficos/01_fruto_tres_categorias.png",
  plot = grafico_fruto_3cat,
  width = 9,
  height = 6,
  dpi = 300
)
# Gráfico 2. Altura de plantas
grafico_altura <- ggplot(
  base_4en1,
  aes(x = reorder(as.factor(no_planta), altura_cm), y = altura_cm, fill = fruto_3cat)
) +
  geom_col(color = "black") +
  coord_flip() +
  scale_fill_manual(
    values = c(
      "No visible" = color_rojo,
      "Visible" = color_turquesa,
      "Abundante" = color_amarillo
    )
  ) +
  labs(
    title = "Altura de plantas de café según categoría de fruto",
    subtitle = "Cada barra representa una planta evaluada",
    x = "Planta",
    y = "Altura en cm",
    fill = "Fruto"
  ) +
  theme_minimal(base_size = 13)

print(grafico_altura)

ggsave(
  "resultados_cafe_rstudio/graficos/02_altura_plantas_fruto.png",
  plot = grafico_altura,
  width = 10,
  height = 8,
  dpi = 300
)
# Gráfico 3. Temperatura antes y después
datos_temp_largo <- base_4en1 %>%
  select(no_planta, temp_sin_lluvia, temp_post_lluvia) %>%
  pivot_longer(
    cols = c(temp_sin_lluvia, temp_post_lluvia),
    names_to = "momento",
    values_to = "temperatura"
  ) %>%
  mutate(
    momento = factor(
      momento,
      levels = c("temp_sin_lluvia", "temp_post_lluvia"),
      labels = c("Antes de lluvia", "Después de lluvia")
    )
  )

grafico_temp <- ggplot(datos_temp_largo, aes(x = momento, y = temperatura, fill = momento)) +
  geom_boxplot(color = "black", alpha = 0.85) +
  geom_jitter(width = 0.12, color = "#263238", size = 2.5) +
  scale_fill_manual(values = c("Antes de lluvia" = color_naranja, "Después de lluvia" = color_azul)) +
  labs(
    title = "Temperatura antes y después de la lluvia",
    subtitle = "Comparación microambiental en 28 plantas",
    x = "Momento",
    y = "Temperatura en °C",
    fill = "Momento"
  ) +
  theme_minimal(base_size = 13)

print(grafico_temp)

ggsave(
  "resultados_cafe_rstudio/graficos/03_temperatura_antes_despues.png",
  plot = grafico_temp,
  width = 9,
  height = 6,
  dpi = 300
)
# Gráfico 4. pH antes y después
datos_ph_largo <- base_4en1 %>%
  select(no_planta, ph_sin_lluvia, ph_post_lluvia) %>%
  pivot_longer(
    cols = c(ph_sin_lluvia, ph_post_lluvia),
    names_to = "momento",
    values_to = "ph"
  ) %>%
  mutate(
    momento = factor(
      momento,
      levels = c("ph_sin_lluvia", "ph_post_lluvia"),
      labels = c("Antes de lluvia", "Después de lluvia")
    )
  )

grafico_ph <- ggplot(datos_ph_largo, aes(x = momento, y = ph, fill = momento)) +
  geom_boxplot(color = "black", alpha = 0.85) +
  geom_jitter(width = 0.12, color = "#263238", size = 2.5) +
  scale_fill_manual(values = c("Antes de lluvia" = color_morado, "Después de lluvia" = color_verde)) +
  labs(
    title = "pH del suelo antes y después de la lluvia",
    subtitle = "Desplazamiento del pH posterior al evento de lluvia",
    x = "Momento",
    y = "pH",
    fill = "Momento"
  ) +
  theme_minimal(base_size = 13)

print(grafico_ph)

ggsave(
  "resultados_cafe_rstudio/graficos/04_ph_antes_despues.png",
  plot = grafico_ph,
  width = 9,
  height = 6,
  dpi = 300
)
# Gráfico 5. pH posterior según fruto en tres categorías
grafico_ph_fruto_3cat <- ggplot(
  base_4en1,
  aes(x = fruto_3cat, y = ph_post_lluvia, fill = fruto_3cat)
) +
  geom_boxplot(color = "black", alpha = 0.85) +
  geom_jitter(width = 0.12, color = "#263238", size = 2.5) +
  scale_fill_manual(
    values = c(
      "No visible" = color_rojo,
      "Visible" = color_turquesa,
      "Abundante" = color_amarillo
    )
  ) +
  labs(
    title = "pH posterior según categoría de fruto",
    subtitle = "No visible, visible y abundante",
    x = "Categoría de fruto",
    y = "pH posterior a la lluvia",
    fill = "Fruto"
  ) +
  theme_minimal(base_size = 13)

print(grafico_ph_fruto_3cat)

ggsave(
  "resultados_cafe_rstudio/graficos/05_ph_fruto_tres_categorias.png",
  plot = grafico_ph_fruto_3cat,
  width = 9,
  height = 6,
  dpi = 300
)
# Gráfico 6. Curva logística simple
grafico_logistico <- ggplot(base_4en1, aes(x = ph_post_lluvia, y = fruto_bin)) +
  geom_point(aes(color = fruto_3cat), size = 3) +
  stat_smooth(
    method = "glm",
    method.args = list(family = "binomial"),
    se = TRUE,
    color = color_azul,
    fill = "#BBDEFB",
    linewidth = 1.2
  ) +
  scale_color_manual(
    values = c(
      "No visible" = color_rojo,
      "Visible" = color_turquesa,
      "Abundante" = color_amarillo
    )
  ) +
  labs(
    title = "Modelo logístico simple",
    subtitle = "Probabilidad de fruto visible según pH posterior a la lluvia",
    x = "pH posterior a la lluvia",
    y = "Probabilidad estimada de fruto visible",
    color = "Fruto"
  ) +
  theme_minimal(base_size = 13)

print(grafico_logistico)
## `geom_smooth()` using formula = 'y ~ x'

ggsave(
  "resultados_cafe_rstudio/graficos/06_modelo_logistico_ph.png",
  plot = grafico_logistico,
  width = 9,
  height = 6,
  dpi = 300
)
## `geom_smooth()` using formula = 'y ~ x'
# Gráfico 7. Probabilidad estimada según pH
grafico_prob_ph <- ggplot(rango_ph, aes(x = ph_post_lluvia, y = prob_fruto)) +
  geom_line(color = color_rosado, linewidth = 1.4) +
  geom_point(color = color_azul, size = 1.8) +
  scale_y_continuous(labels = percent_format(accuracy = 1)) +
  labs(
    title = "Probabilidad estimada de fruto visible",
    subtitle = "Estimación exploratoria a partir del pH posterior a la lluvia",
    x = "pH posterior a la lluvia",
    y = "Probabilidad estimada"
  ) +
  theme_minimal(base_size = 13)

print(grafico_prob_ph)

ggsave(
  "resultados_cafe_rstudio/graficos/07_probabilidad_fruto_ph.png",
  plot = grafico_prob_ph,
  width = 9,
  height = 6,
  dpi = 300
)
# Gráfico 8. Serie temporal Micro:bit por tiempo acumulado
grafico_micro_tiempo <- ggplot(base_micro, aes(x = tiempo_min)) +
  geom_line(
    aes(y = hum_zona_inclinada_zona_baja, color = "Zona inclinada baja"),
    linewidth = 1.2
  ) +
  geom_line(
    aes(y = hum_zona_alta_poca_inclinacion, color = "Zona alta poca inclinación"),
    linewidth = 1.2
  ) +
  scale_color_manual(
    values = c(
      "Zona inclinada baja" = color_naranja,
      "Zona alta poca inclinación" = color_azul
    )
  ) +
  labs(
    title = "Serie temporal de humedad del suelo con Micro:bit",
    subtitle = "Seguimiento por tiempo acumulado en minutos",
    x = "Tiempo en minutos",
    y = "Humedad relativa del sensor",
    color = "Zona"
  ) +
  theme_minimal(base_size = 13)

print(grafico_micro_tiempo)

ggsave(
  "resultados_cafe_rstudio/graficos/08_microbit_tiempo_min.png",
  plot = grafico_micro_tiempo,
  width = 10,
  height = 6,
  dpi = 300
)
# Gráfico 9. Serie temporal por hora de toma
if(sum(!is.na(base_micro$hora_toma_formato)) > 0){
  
  grafico_micro_hora <- ggplot(base_micro, aes(x = hora_toma_formato)) +
    geom_line(
      aes(y = hum_zona_inclinada_zona_baja, color = "Zona inclinada baja"),
      linewidth = 1.2
    ) +
    geom_line(
      aes(y = hum_zona_alta_poca_inclinacion, color = "Zona alta poca inclinación"),
      linewidth = 1.2
    ) +
    geom_point(
      aes(y = hum_zona_inclinada_zona_baja),
      color = color_naranja,
      size = 2
    ) +
    geom_point(
      aes(y = hum_zona_alta_poca_inclinacion),
      color = color_azul,
      size = 2
    ) +
    scale_color_manual(
      values = c(
        "Zona inclinada baja" = color_naranja,
        "Zona alta poca inclinación" = color_azul
      )
    ) +
    labs(
      title = "Humedad del suelo según hora de toma",
      subtitle = "Serie horaria, no semanal",
      x = "Hora de toma",
      y = "Humedad relativa del sensor",
      color = "Zona"
    ) +
    theme_minimal(base_size = 13)
  
  print(grafico_micro_hora)
  
  ggsave(
    "resultados_cafe_rstudio/graficos/09_microbit_hora_toma.png",
    plot = grafico_micro_hora,
    width = 10,
    height = 6,
    dpi = 300
  )
}
# Gráfico 10. Humedad zona alta según clima
grafico_micro_clima <- ggplot(
  base_micro,
  aes(x = clima_cat, y = hum_zona_alta_poca_inclinacion, fill = clima_cat)
) +
  geom_boxplot(color = "black", alpha = 0.85) +
  geom_jitter(width = 0.12, color = "#263238", size = 2.4) +
  scale_fill_manual(values = c("Sin lluvia" = color_verde, "Con lluvia" = color_azul)) +
  labs(
    title = "Humedad en zona alta según condición climática",
    subtitle = "Lecturas relativas del sensor Micro:bit",
    x = "Condición climática",
    y = "Humedad relativa del sensor",
    fill = "Clima"
  ) +
  theme_minimal(base_size = 13)

print(grafico_micro_clima)

ggsave(
  "resultados_cafe_rstudio/graficos/10_microbit_clima_zona_alta.png",
  plot = grafico_micro_clima,
  width = 9,
  height = 6,
  dpi = 300
)


# ============================================================
# 25. EXPORTAR RESULTADOS A EXCEL
# ============================================================

wb <- createWorkbook()

addWorksheet(wb, "Muestreo")
writeData(wb, "Muestreo", muestreo_resumen)

addWorksheet(wb, "Descriptivos_4en1")
writeData(wb, "Descriptivos_4en1", descriptivos_4en1)

addWorksheet(wb, "Frecuencia_fruto_3cat")
writeData(wb, "Frecuencia_fruto_3cat", frecuencia_fruto_3cat)

addWorksheet(wb, "Frecuencia_fruto_bin")
writeData(wb, "Frecuencia_fruto_bin", frecuencia_fruto)

addWorksheet(wb, "Frecuencia_flor")
writeData(wb, "Frecuencia_flor", frecuencia_flor)

addWorksheet(wb, "Frecuencia_humedad")
writeData(wb, "Frecuencia_humedad", frecuencia_humedad_post)

addWorksheet(wb, "Frecuencia_vigor")
writeData(wb, "Frecuencia_vigor", frecuencia_vigor)

addWorksheet(wb, "Antes_despues")
writeData(wb, "Antes_despues", comparacion_antes_despues)

addWorksheet(wb, "Chi_cuadrado")
writeData(wb, "Chi_cuadrado", resumen_chi)

addWorksheet(wb, "Pruebas_T")
writeData(wb, "Pruebas_T", resumen_t)

addWorksheet(wb, "Correlaciones_fruto")
writeData(wb, "Correlaciones_fruto", correlaciones_fruto)

addWorksheet(wb, "Modelo_simple")
writeData(wb, "Modelo_simple", coef_simple)

addWorksheet(wb, "Modelo_multiple")
writeData(wb, "Modelo_multiple", coef_multiple)

addWorksheet(wb, "Comparacion_modelos")
writeData(wb, "Comparacion_modelos", comparacion_modelos)

addWorksheet(wb, "Clasificacion_simple")
writeData(wb, "Clasificacion_simple", as.data.frame.matrix(clas_simple$matriz), rowNames = TRUE)
writeData(wb, "Clasificacion_simple", clas_simple$resumen, startRow = 6)

addWorksheet(wb, "Clasificacion_multiple")
writeData(wb, "Clasificacion_multiple", as.data.frame.matrix(clas_multiple$matriz), rowNames = TRUE)
writeData(wb, "Clasificacion_multiple", clas_multiple$resumen, startRow = 6)

addWorksheet(wb, "Descriptivos_micro")
writeData(wb, "Descriptivos_micro", descriptivos_micro)

addWorksheet(wb, "Probabilidad_ph")
writeData(wb, "Probabilidad_ph", rango_ph)

saveWorkbook(
  wb,
  "resultados_cafe_rstudio/tablas/Resultados_contraste_RStudio_Cafe.xlsx",
  overwrite = TRUE
)


# ============================================================
# 26. INTERPRETACIONES TEXTUALES
# ============================================================

cat("\n============================================================\n")
## 
## ============================================================
cat("INTERPRETACIÓN GENERAL\n")
## INTERPRETACIÓN GENERAL
cat("============================================================\n")
## ============================================================
cat("\n1. Contexto:\n")
## 
## 1. Contexto:
cat("El estudio caracteriza un lote de café variedad Castillo en la finca El Guayabo.\n")
## El estudio caracteriza un lote de café variedad Castillo en la finca El Guayabo.
cat("La base 4 en 1 trabaja con plantas individuales, mientras que la base Micro:bit trabaja con registros temporales.\n")
## La base 4 en 1 trabaja con plantas individuales, mientras que la base Micro:bit trabaja con registros temporales.
cat("\n2. Muestreo:\n")
## 
## 2. Muestreo:
cat("La muestra de 28 plantas corresponde a un muestreo no probabilístico por conveniencia.\n")
## La muestra de 28 plantas corresponde a un muestreo no probabilístico por conveniencia.
cat("La fracción aproximada de muestreo es de ", round(fraccion_muestreo * 100, 1), "% del lote estimado.\n", sep = "")
## La fracción aproximada de muestreo es de 14% del lote estimado.
cat("\n3. Fruto:\n")
## 
## 3. Fruto:
cat("La variable Fruto se conserva en tres categorías para la descripción: No visible, Visible y Abundante.\n")
## La variable Fruto se conserva en tres categorías para la descripción: No visible, Visible y Abundante.
cat("Para la regresión logística se recodifica como variable binaria: 0 = No visible y 1 = Visible o Abundante.\n")
## Para la regresión logística se recodifica como variable binaria: 0 = No visible y 1 = Visible o Abundante.
cat("\n4. Contraste con SPSS:\n")
## 
## 4. Contraste con SPSS:
cat("El análisis en RStudio permite contrastar los resultados obtenidos previamente en SPSS.\n")
## El análisis en RStudio permite contrastar los resultados obtenidos previamente en SPSS.
cat("Se revisan descriptivos, pruebas Chi-cuadrado, pruebas T, correlaciones, regresión logística, AIC y matriz de clasificación.\n")
## Se revisan descriptivos, pruebas Chi-cuadrado, pruebas T, correlaciones, regresión logística, AIC y matriz de clasificación.
cat("\n5. Predicción exploratoria:\n")
## 
## 5. Predicción exploratoria:
cat("La predicción de fruto visible se realiza únicamente con la base por planta.\n")
## La predicción de fruto visible se realiza únicamente con la base por planta.
cat("El modelo logístico simple estima la probabilidad de fruto visible a partir del pH posterior a la lluvia.\n")
## El modelo logístico simple estima la probabilidad de fruto visible a partir del pH posterior a la lluvia.
cat("Esta predicción es exploratoria y no debe interpretarse como sistema predictivo definitivo.\n")
## Esta predicción es exploratoria y no debe interpretarse como sistema predictivo definitivo.
cat("\n6. Serie temporal:\n")
## 
## 6. Serie temporal:
cat("La base Micro:bit permite construir una serie temporal por hora de toma y por tiempo acumulado en minutos.\n")
## La base Micro:bit permite construir una serie temporal por hora de toma y por tiempo acumulado en minutos.
cat("No se construye una serie semanal 2026 porque no existe una variable de fecha o semana calendario.\n")
## No se construye una serie semanal 2026 porque no existe una variable de fecha o semana calendario.
cat("\n7. No fusión directa:\n")
## 
## 7. No fusión directa:
cat("No se fusionan directamente las bases 4 en 1 y Micro:bit porque tienen unidades de análisis diferentes.\n")
## No se fusionan directamente las bases 4 en 1 y Micro:bit porque tienen unidades de análisis diferentes.
cat("Una base trabaja por planta y la otra por tiempo.\n")
## Una base trabaja por planta y la otra por tiempo.
# ============================================================
# 27. CONCLUSIONES
# ============================================================

cat("\n============================================================\n")
## 
## ============================================================
cat("CONCLUSIONES\n")
## CONCLUSIONES
cat("============================================================\n")
## ============================================================
cat("\n1. La base 4 en 1 permitió caracterizar 28 plantas de café variedad Castillo mediante variables microambientales y agronómicas.\n")
## 
## 1. La base 4 en 1 permitió caracterizar 28 plantas de café variedad Castillo mediante variables microambientales y agronómicas.
cat("\n2. La comparación antes y después de la lluvia permite reconocer cambios en temperatura, pH y humedad, coherentes con el evento de precipitación.\n")
## 
## 2. La comparación antes y después de la lluvia permite reconocer cambios en temperatura, pH y humedad, coherentes con el evento de precipitación.
cat("\n3. La variable Fruto puede analizarse en tres categorías para fines descriptivos y en formato binario para regresión logística.\n")
## 
## 3. La variable Fruto puede analizarse en tres categorías para fines descriptivos y en formato binario para regresión logística.
cat("\n4. El pH posterior a la lluvia se mantiene como variable relevante para explicar de forma exploratoria la presencia de fruto visible.\n")
## 
## 4. El pH posterior a la lluvia se mantiene como variable relevante para explicar de forma exploratoria la presencia de fruto visible.
cat("\n5. El modelo logístico simple permite estimar probabilidades de presencia de fruto visible, pero su capacidad predictiva debe considerarse limitada por el tamaño de muestra.\n")
## 
## 5. El modelo logístico simple permite estimar probabilidades de presencia de fruto visible, pero su capacidad predictiva debe considerarse limitada por el tamaño de muestra.
cat("\n6. La base Micro:bit permite analizar la humedad del suelo como serie temporal por hora de toma y por tiempo acumulado.\n")
## 
## 6. La base Micro:bit permite analizar la humedad del suelo como serie temporal por hora de toma y por tiempo acumulado.
cat("\n7. La serie Micro:bit no debe usarse directamente para predecir fruto porque sus registros no están asociados planta por planta.\n")
## 
## 7. La serie Micro:bit no debe usarse directamente para predecir fruto porque sus registros no están asociados planta por planta.
cat("\n8. El contraste entre SPSS y RStudio fortalece la consistencia del análisis y permite generar gráficos más claros para presentación.\n")
## 
## 8. El contraste entre SPSS y RStudio fortalece la consistencia del análisis y permite generar gráficos más claros para presentación.
# ============================================================
# 28. RECOMENDACIONES
# ============================================================

cat("\n============================================================\n")
## 
## ============================================================
cat("RECOMENDACIONES\n")
## RECOMENDACIONES
cat("============================================================\n")
## ============================================================
cat("\n1. Mantener la base 4 en 1 como fuente principal para la predicción exploratoria de fruto visible.\n")
## 
## 1. Mantener la base 4 en 1 como fuente principal para la predicción exploratoria de fruto visible.
cat("\n2. Usar la base Micro:bit exclusivamente para análisis temporal de humedad del suelo.\n")
## 
## 2. Usar la base Micro:bit exclusivamente para análisis temporal de humedad del suelo.
cat("\n3. No reportar serie semanal 2026 mientras no exista una variable de fecha o semana.\n")
## 
## 3. No reportar serie semanal 2026 mientras no exista una variable de fecha o semana.
cat("\n4. Ampliar el número de plantas evaluadas para mejorar la estabilidad de los modelos logísticos.\n")
## 
## 4. Ampliar el número de plantas evaluadas para mejorar la estabilidad de los modelos logísticos.
cat("\n5. Registrar mediciones por planta en varios momentos si se desea construir modelos longitudinales o semanales de fruto.\n")
## 
## 5. Registrar mediciones por planta en varios momentos si se desea construir modelos longitudinales o semanales de fruto.
cat("\n6. Incluir nuevas variables agronómicas como diámetro del tallo, número de hojas, producción por planta y estado sanitario.\n")
## 
## 6. Incluir nuevas variables agronómicas como diámetro del tallo, número de hojas, producción por planta y estado sanitario.
cat("\n7. Integrar los resultados gráficos al tablero Semáforo del Cultivo en Power BI.\n")
## 
## 7. Integrar los resultados gráficos al tablero Semáforo del Cultivo en Power BI.
cat("\n8. Interpretar todos los hallazgos como asociaciones exploratorias, no causales.\n")
## 
## 8. Interpretar todos los hallazgos como asociaciones exploratorias, no causales.
cat("\n9. Hacer uso de mas sensores de microbit en estudios longitudinales.\n")
## 
## 9. Hacer uso de mas sensores de microbit en estudios longitudinales.
cat("\n10. Generar un Tbalero agronomicos en el cultivo de café con el fin de hacer seguimiento continuo
    a los procesos productivos.\n")
## 
## 10. Generar un Tbalero agronomicos en el cultivo de café con el fin de hacer seguimiento continuo
##     a los procesos productivos.
# ============================================================
# 29. CIERRE FINAL
# ============================================================

cat("\n============================================================\n")
## 
## ============================================================
cat("CIERRE DEL ANÁLISIS\n")
## CIERRE DEL ANÁLISIS
cat("============================================================\n")
## ============================================================
cat("\nEl análisis final en RStudio permite contrastar los resultados previos de SPSS,\n")
## 
## El análisis final en RStudio permite contrastar los resultados previos de SPSS,
cat("mantener la estructura metodológica del trabajo ya realizado y complementar el estudio\n")
## mantener la estructura metodológica del trabajo ya realizado y complementar el estudio
cat("con gráficos llamativos, análisis temporal por hora, correlaciones exploratorias y regresión logística.\n")
## con gráficos llamativos, análisis temporal por hora, correlaciones exploratorias y regresión logística.
cat("La predicción se limita a la base por planta y la serie temporal se limita a la humedad Micro:bit.\n")
## La predicción se limita a la base por planta y la serie temporal se limita a la humedad Micro:bit.
cat("Los resultados deben interpretarse como exploratorios y no causales.\n")
## Los resultados deben interpretarse como exploratorios y no causales.
cat("\n\nArchivos generados:\n")
## 
## 
## Archivos generados:
cat("1. resultados_cafe_rstudio/tablas/Resultados_contraste_RStudio_Cafe.xlsx\n")
## 1. resultados_cafe_rstudio/tablas/Resultados_contraste_RStudio_Cafe.xlsx
cat("2. Carpeta de gráficos: resultados_cafe_rstudio/graficos\n")
## 2. Carpeta de gráficos: resultados_cafe_rstudio/graficos
# ============================================================
# CIERRE DEL SCRIPT
# ============================================================