# ==================================================================================
# PROYECTO FINAL: ANÁLISIS ESTADÍSTICO DE ACCIDENT LATITUDE
# ==================================================================================

# 1. CARGA DE LIBRERÍAS
library(readxl)   # Para leer Excel
library(ggplot2)  # Para gráficas
library(dplyr)    # Para manejo de datos
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(gt)       # Para tablas profesionales
library(janitor)  # Para totales
## 
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
# 2. IMPORTACIÓN Y PROCESAMIENTO DE DATOS
# Importamos el archivo asegurando que el objeto 'database' exista
database <- read_excel("database.xlsx")
## Warning: Expecting numeric in C2189 / R2189C3: got 'Accident Year'
## Warning: Expecting numeric in C2215 / R2215C3: got 'Accident Year'
nombre_var <- "Accident Latitude"
ANCHO_CLASE <- 3.0 

# Limpieza: Convertir a número y eliminar valores nulos
datos_raw <- as.numeric(as.character(database[[nombre_var]])) %>% na.omit()

LIMITE_MIN <- floor(min(datos_raw))
LIMITE_MAX <- ceiling(max(datos_raw))
variable_filtrada <- datos_raw[datos_raw >= LIMITE_MIN & datos_raw <= LIMITE_MAX]
n_total <- length(variable_filtrada)

# 3. CONSTRUCCIÓN DE TABLA DE FRECUENCIAS (Incluye ni, hi, Ni asc y Ni desc)
cortes <- seq(LIMITE_MIN, LIMITE_MAX + ANCHO_CLASE, by = ANCHO_CLASE)
tabla_resumen <- data.frame(
  Intervalo = cut(variable_filtrada, breaks = cortes, include.lowest = TRUE, right = FALSE)
) %>%
  count(Intervalo, name = "ni") %>%
  mutate(
    hi = ni / sum(ni),          # Frecuencia relativa (Suma 1.00)
    Ni_asc = cumsum(ni),        # Frecuencia acumulada ascendente
    Ni_desc = n_total - Ni_asc + ni # Frecuencia acumulada descendente
  )

# 4. VISUALIZACIÓN DE LA TABLA
tabla_resumen %>%
  adorn_totals("row", name = "TOTAL") %>%
  gt() %>% 
  fmt_number(columns = hi, decimals = 4) %>% # Formato hi con decimales
  tab_header(title = "Distribución de Frecuencias", subtitle = "Variable: Accident Latitude")
Distribución de Frecuencias
Variable: Accident Latitude
Intervalo ni hi Ni_asc Ni_desc
[18,21) 1 0.0004 1 2795
[21,24) 4 0.0014 5 2794
[24,27) 2 0.0007 7 2790
[27,30) 483 0.1728 490 2788
[30,33) 646 0.2311 1136 2305
[33,36) 466 0.1667 1602 1659
[36,39) 350 0.1252 1952 1193
[39,42) 505 0.1807 2457 843
[42,45) 172 0.0615 2629 338
[45,48) 126 0.0451 2755 166
[48,51) 29 0.0104 2784 40
[63,66) 3 0.0011 2787 11
[66,69) 3 0.0011 2790 8
[69,72] 5 0.0018 2795 5
TOTAL 2795 1.0000 24190 17735
# 5. GRÁFICAS (Histograma, Ojivas y Boxplot)
# Histograma
ggplot(tabla_resumen, aes(x = Intervalo, y = ni)) +
  geom_col(fill = "#708090", color = "white") +
  geom_text(aes(label = ni), vjust = -0.5, fontface = "bold") +
  theme_minimal() + 
  labs(title = "Frecuencia de Accidentes por Latitud", x = "Rango Geográfico", y = "Número de Accidentes")

# Cruce de Ojivas
puntos_x <- seq(LIMITE_MIN, LIMITE_MIN + (nrow(tabla_resumen) * ANCHO_CLASE), by = ANCHO_CLASE)
df_ojiva <- data.frame(
  X = rep(puntos_x, 2), 
  Y = c(c(0, tabla_resumen$Ni_asc), c(n_total, tabla_resumen$Ni_desc[-1], 0)),
  Tipo = rep(c("Ascendente", "Descendente"), each = length(puntos_x))
)

ggplot(df_ojiva, aes(x = X, y = Y, color = Tipo, group = Tipo)) +
  geom_line(linewidth = 1.2) + geom_point(shape = 16, size = 3) + 
  scale_color_manual(values = c("#6B8E23", "#BC8F8F")) +
  theme_minimal() + labs(title = "Análisis de Frecuencia Acumulada", y = "Total Acumulado de Accidentes")

# Boxplot Horizontal
ggplot(data.frame(v = variable_filtrada), aes(x = "", y = v)) +
  geom_boxplot(fill = "#8FBC8F", color = "#2F4F4F", outlier.color = "red", outlier.shape = 16) +
  coord_flip() + theme_bw() + labs(title = "Dispersión Geográfica", y = "Grados de Latitud")

# 6. CONCLUSIÓN GENERAL
cat("\nCONCLUSIÓN GENERAL:\n")
## 
## CONCLUSIÓN GENERAL:
cat("El análisis identifica concentraciones críticas en rangos latitudinales específicos.\n")
## El análisis identifica concentraciones críticas en rangos latitudinales específicos.
cat("La suma de hi es exactamente 1.00, validando la integridad de los 2,795 registros.\n")
## La suma de hi es exactamente 1.00, validando la integridad de los 2,795 registros.