El primer paso crítico en cualquier análisis de datos es la importación correcta de la fuente de información. En esta sección, se utiliza la función read.csv() para cargar el archivo de datos externo al entorno de trabajo de R. Este proceso transforma los datos crudos en un “data frame”, permitiendo que el software reconozca las columnas y filas para su posterior manipulación.
database <- read.csv("database-_1_.csv", header = TRUE, sep = ",", dec = ".", check.names = FALSE)
raw_years <- database$`Accident Year`
raw_years <- raw_years[raw_years != ""]
raw_years <- na.omit(raw_years)
years_obj <- floor(as.numeric(as.character(raw_years)))
## Warning: NAs introducidos por coerción
years_num <- as.numeric(years_obj)
years_num <- na.omit(years_num)
years_obj <- years_obj[!is.na(years_num)]
valid_indices <- years_num > 1900 & years_num <= 2025
years_num <- years_num[valid_indices]
years_obj <- years_obj[valid_indices]
Una vez cargados los datos, el siguiente paso es la organización mediante tablas de frecuencia. Esta técnica estadística agrupa la información de una variable específica (como el año o la causa del accidente) para contar cuántas veces ocurre cada evento.
#tabla de frecuencia
datos <- read.csv("database-_1_.csv", stringsAsFactors = FALSE)
anios_limpios <- floor(as.numeric(datos$Accident.Year))
## Warning: NAs introducidos por coerción
anios_limpios <- anios_limpios[!is.na(anios_limpios)]
tabla_base <- table(anios_limpios)
ni <- as.vector(tabla_base)
Magnitud <- names(tabla_base)
hi <- round(ni/sum(ni)*100, 2)
diferencia <- 100 - sum(hi)
if(diferencia != 0){
indice_max <- which.max(ni)
hi[indice_max] <- hi[indice_max] + diferencia
}
Ni_asc <- cumsum(ni)
Ni_dsc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_dsc <- rev(cumsum(rev(hi)))
TDFMagnitudFin <- data.frame(Magnitud, ni, hi, Ni_asc, Ni_dsc, Hi_asc, Hi_dsc)
library(knitr)
kable(TDFMagnitudFin,
caption = "Tabla de Frecuencia de accidentes del año",
align = "c",
col.names = c("Año", "ni", "hi (%)", "Ni Asc", "Ni Dsc", "Hi Asc", "Hi Dsc"))
| Año | ni | hi (%) | Ni Asc | Ni Dsc | Hi Asc | Hi Dsc |
|---|---|---|---|---|---|---|
| 2010 | 350 | 12.53 | 350 | 2793 | 12.53 | 100.00 |
| 2011 | 345 | 12.35 | 695 | 2443 | 24.88 | 87.47 |
| 2012 | 366 | 13.10 | 1061 | 2098 | 37.98 | 75.12 |
| 2013 | 401 | 14.36 | 1462 | 1732 | 52.34 | 62.02 |
| 2014 | 454 | 16.25 | 1916 | 1331 | 68.59 | 47.66 |
| 2015 | 576 | 20.63 | 2492 | 877 | 89.22 | 31.41 |
| 2016 | 301 | 10.78 | 2793 | 301 | 100.00 | 10.78 |
Tras observar el comportamiento general, este apartado se enfoca en el análisis de una zona o segmento específico (distribución local). Esta comparación es vital para determinar si las tendencias de la región estudiada se mantienen alineadas con los promedios globales o si presentan anomalías particulares que requieran una intervención diferenciada.
library(ggplot2)
##
## Adjuntando el paquete: 'ggplot2'
## The following object is masked from 'package:e1071':
##
## element
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
p_global <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = ni)) +
geom_histogram(bins = 7, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = seq(min(TDFMagnitudFin$Magnitud), max(TDFMagnitudFin$Magnitud), by = 1)) +
scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
labs(title = "Gráfica No 1: Histograma de Distribución de Accidentes",
subtitle = "Análisis por intervalos de tiempo",
x = "Año",
y = "Frecuencia de Accidentes") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_global)
El histograma de distribución de accidentes por intervalos de tiempo muestra la frecuencia de eventos ocurridos anualmente. Esta visualización es clave para detectar patrones cíclicos o años atípicos en los que la cantidad de accidentes se desvió significativamente del promedio histórico.
library(ggplot2)
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
max_ni <- max(TDFMagnitudFin$ni)
p_ni_local <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = ni)) +
geom_histogram(binwidth = 1, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, max_ni * 1.05),
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 2: Distribución de Accidentes por Intervalos de Tiempo.",
subtitle = "Formato de histograma para análisis de distribución",
x = "Año",
y = "Cantidad") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ni_local)
Para validar la representatividad de la muestra local, se analiza aquí la incidencia porcentual a nivel global. Este enfoque permite normalizar los datos y comparar la participación de cada categoría de causa frente al universo total de accidentes registrados en el dataset.
library(ggplot2)
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
total_hi <- sum(TDFMagnitudFin$hi)
p_hi_global <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = hi)) +
geom_histogram(binwidth = 1, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, max(TDFMagnitudFin$hi) * 1.2),
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 3: Histograma de Participación Porcentual",
x = "Año",
y = "Porcentaje (%)") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_hi_global)
Más allá de los números totales, es fundamental entender el peso porcentual de cada causa. En esta sección se transforman las frecuencias absolutas en valores relativos, facilitando la interpretación de la probabilidad de ocurrencia de cada tipo de accidente dentro del entorno local.
# Histogram_localhi_updated
library(ggplot2)
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
max_hi <- max(TDFMagnitudFin$hi)
p_hi_local <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = hi)) +
geom_histogram(binwidth = 1, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, max_hi * 1.1),
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 4: Histograma de Incidencia Relativa de Accidentes",
x = "Año",
y = "Porcentaje (%)") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_hi_local)
La ojiva es una representación gráfica que permite observar cómo se acumulan los accidentes a medida que sumamos cada categoría de causa en el entorno local. A diferencia de las gráficas de barras tradicionales, la ojiva se enfoca en el crecimiento porcentual acumulado, facilitando la identificación del punto en el que se alcanza la mayoría de la siniestralidad.
library(ggplot2)
total_n <- max(TDFMagnitudFin$Ni_asc)
p_ojiva_ni <- ggplot(TDFMagnitudFin, aes(x = Magnitud)) +
geom_line(aes(y = Ni_asc, color = "Ni Ascendente"), linewidth = 1) +
geom_point(aes(y = Ni_asc, color = "Ni Ascendente"), size = 2.5) +
geom_line(aes(y = Ni_dsc, color = "Ni Descendente"), linewidth = 1) +
geom_point(aes(y = Ni_dsc, color = "Ni Descendente"), size = 2.5) +
scale_color_manual(name = "Tipo de Acumulado",
values = c("Ni Ascendente" = "steelblue",
"Ni Descendente" = "firebrick")) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, total_n * 1.05), # Un 5% extra arriba
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 5: Comportamiento de la cantidad Acumulada de Accidentes.",
x = "Año",
y = "Cantidad Acumulada") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
legend.position = "bottom", # Leyenda en la parte inferior
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ojiva_ni)
#La Gráfica No. 5 muestra la acumulación absoluta de accidentes ($N_i$), donde la curva azul asciende progresivamente hasta alcanzar un total cercano a los 2800 eventos en 2016, mientras la roja desciende desde esa misma cifra. El cruce de ambas líneas, ocurrido poco después de 2013 y alrededor de los 1400 casos, marca visualmente la mediana, indicando el punto donde se registró la mitad del total de siniestros.
Esta sección presenta la ojiva a nivel global, permitiendo analizar el comportamiento acumulativo de toda la base de datos. El objetivo es verificar la estabilidad del sistema y determinar si el patrón de acumulación de riesgos es constante en todas las operaciones registradas.
library(ggplot2)
ymax <- 105
p_ojiva_hi <- ggplot(TDFMagnitudFin, aes(x = Magnitud)) +
geom_line(aes(y = Hi_asc, color = "Hi Ascendente"), linewidth = 1) +
geom_point(aes(y = Hi_asc, color = "Hi Ascendente"), size = 2.5) +
geom_line(aes(y = Hi_dsc, color = "Hi Descendente"), linewidth = 1) +
geom_point(aes(y = Hi_dsc, color = "Hi Descendente"), size = 2.5) +
scale_color_manual(name = "Tipo de Acumulado",
values = c("Hi Ascendente" = "steelblue",
"Hi Descendente" = "firebrick")) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, ymax),
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 6: Comportamiento de la cantidad Relativa de Accidentes.",
x = "Año",
y = "Porcentaje Acumulado") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
legend.position = "bottom", # Leyenda abajo
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ojiva_hi)
#Esta gráfica presenta las curvas de frecuencia acumulada (ojivas) de accidentes ocurridos entre 2010 y 2016, contrastando la acumulación progresiva (línea azul ascendente) frente al porcentaje restante (línea roja descendente). Mientras la curva azul crece hasta completar el 100% de los casos al final del periodo, la roja desciende desde la totalidad inicial, cruzándose ambas líneas poco después del año 2013; este punto de intersección es clave, ya que visualiza la mediana de la distribución temporal, indicando el momento aproximado en el que se había registrado la mitad de los accidentes totales.
El diagrama de cajas es una herramienta estadística que resume la distribución de una variable numérica a través de sus cuartiles. En este reporte, se utiliza para analizar la variabilidad de los accidentes, permitiendo identificar visualmente la mediana, el rango intercuartílico y la presencia de valores extremos que se alejan del comportamiento normal de los datos.
library(ggplot2)
par(mar = c(5, 2, 4, 2))
boxplot(anios_limpios,
horizontal = TRUE,
col = "skyblue",
main = "Gráfica 7: Distribución de Años (Boxplot)",
xlab = "Año",
xaxt = "n",
outline = TRUE,
pch = 19,
outcol = "red")
axis(1,
at = sort(unique(anios_limpios)),
labels = sort(unique(anios_limpios)),
las = 2,
cex.axis = 0.8)
grid(nx = NULL, ny = NA, col = "lightgray", lty = "dotted")
#Esta gráfica de caja muestra la distribución temporal de un conjunto de datos que abarca desde el año 2010 hasta el 2016. Se observa que el 50% central de la información (la caja azul) está concentrado entre los años 2012 y 2015, con una mediana situada exactamente en 2013 que divide la muestra en dos partes iguales. La longitud desigual de las secciones de la caja sugiere que los datos están más dispersos en los años recientes (entre 2013 y 2015) en comparación con el periodo inicial, indicando una variabilidad ligeramente mayor hacia el final del rango temporal analizado.
Más allá de las representaciones visuales, el rigor de una investigación de datos reside en sus indicadores numéricos. En esta sección se presentan las medidas de tendencia central y descriptivas calculadas directamente desde el dataset mediante R. El objetivo es proporcionar una conclusión objetiva que elimine cualquier ambigüedad interpretativa sobre los riesgos analizados.
library(e1071)
# 1. Rango (Mínimo y Máximo)
ri <- min(anios_limpios, na.rm = TRUE)
rs <- max(anios_limpios, na.rm = TRUE)
print(ri)
## [1] 2010
print(rs)
## [1] 2016
# 2. Mediana
mediana <- median(anios_limpios, na.rm = TRUE)
print(mediana)
## [1] 2013
# 3. Media Aritmética
media_aritmetica <- mean(anios_limpios, na.rm = TRUE)
print(media_aritmetica)
## [1] 2013.144
# 4. Moda (Calculada como el valor más frecuente)
t <- table(anios_limpios)
Mo <- as.numeric(names(t)[which.max(t)])
print(Mo)
## [1] 2015
# 5. Desviación Estándar
# Aquí es directo, el resultado es en "años"
desviacion_estandar <- sd(anios_limpios, na.rm = TRUE)
print(paste(round(desviacion_estandar, 2), "años"))
## [1] "1.92 años"
# 6. Coeficiente de Variabilidad
coeficiente_variabilidad <- (desviacion_estandar / media_aritmetica) * 100
print(coeficiente_variabilidad)
## [1] 0.09543073
# 7. Asimetría (Skewness)
As <- skewness(anios_limpios, na.rm = TRUE)
print(As)
## [1] -0.1947063
# 8. Curtosis
curtosis_val <- kurtosis(anios_limpios, na.rm = TRUE)
print(curtosis_val)
## [1] -1.180577
Más allá de las representaciones gráficas, la tabla de indicadores proporciona los valores exactos que rigen el comportamiento de los datos. Esta sección presenta un resumen tabular donde se identifican las métricas clave de la variable analizada, permitiendo una lectura rápida y precisa de la realidad estadística del proyecto.
library(knitr)
# Preparamos los textos para la tabla
Variable <- "Accident Year"
Tabla_indicadores <- data.frame(
Variable,
ri, # Mínimo
rs, # Máximo
round(media_aritmetica, 2), # Media
mediana, # Mediana
Mo, # Moda
round(desviacion_estandar, 2), # S (Desviación)
round(coeficiente_variabilidad, 2),
round(As, 2),
round(curtosis_val, 2)
)
colnames(Tabla_indicadores) <- c("Variable","Mínimo","Máximo","x","Me","Mo","S (años)","Cv (%)","As","K")
# Imprimir Tabla
kable(Tabla_indicadores, format = "markdown", align = "c",
caption = "Tabla No. 1: Indicadores estadísticos de la variable Accident Year.")
| Variable | Mínimo | Máximo | x | Me | Mo | S (años) | Cv (%) | As | K |
|---|---|---|---|---|---|---|---|---|---|
| Accident Year | 2010 | 2016 | 2013.14 | 2013 | 2015 | 1.92 | 0.1 | -0.19 | -1.18 |
En estadística, un valor atípico es una observación que se distancia significativamente del resto de los datos. Identificar estos puntos en el reporte es crucial, ya que pueden representar errores de registro o, más importante aún, eventos extraordinarios que requieren una investigación profunda por su alto impacto o naturaleza inusual.
# Usamos boxplot.stats sobre los años
stats_outliers <- boxplot.stats(anios_limpios)$out
# Contar los valores atípicos
num_outliers <- length(stats_outliers)
print(paste("Número de outliers:", num_outliers))
## [1] "Número de outliers: 0"
# Obtener Mínimo y Máximo Outlier (si existen)
minimooutliers <- if(num_outliers > 0) min(stats_outliers) else NA
maximooutliers <- if(num_outliers > 0) max(stats_outliers) else NA
# Imprimir resultados
if(num_outliers > 0){
print(paste("Outlier más bajo:", minimooutliers))
print(paste("Outlier más alto:", maximooutliers))
} else {
print("No existen valores atípicos.")
}
## [1] "No existen valores atípicos."
El análisis de la variable ‘Accident Year’ abarca el periodo entre 2010 y 2016, evidenciando una tendencia central en torno al año 2013, siendo el 2015 el año con mayor frecuencia de siniestros. Los datos presentan una desviación estándar de 1.92 años respecto al promedio. La distribución muestra un coeficiente de asimetría de -0.19, indicando una mayor concentración de eventos en los años más recientes (sesgo negativo), y una curtosis de -1.18, lo que sugiere un comportamiento de tipo platicúrtica (datos dispersos). Finalmente, el diagrama de cajas descartó la existencia de valores atípicos, demostrando que la ocurrencia de accidentes se ha mantenido mayoritariamente dentro de los rangos estadísticos esperados.