Este informe presenta un análisis descriptivo de la sismicidad registrada en Colombia durante los últimos 20 años, con base en el catálogo sísmico exportado (formato USGS). Se abordan cuatro ejes: (1) caracterización por magnitud y profundidad, (2) comportamiento temporal según intensidad, (3) distribución espacial de las zonas con mayor frecuencia de eventos, y (4) conclusiones y recomendaciones orientadas a la toma de decisiones.
# ---- Carga y limpieza de datos ----
# Ajustar la ruta si el archivo .csv no está en el mismo directorio que este .Rmd
sismos_raw <- read.csv("query.csv", stringsAsFactors = FALSE, encoding = "UTF-8")
sismos <- sismos_raw %>%
mutate(
time = ymd_hms(time, tz = "UTC"),
fecha = as_date(time),
anio = year(time),
mes = month(time, label = TRUE, abbr = TRUE, locale = "es_ES.UTF-8"),
hora = hour(time)
) %>%
# Filtro geográfico: eventos en territorio/entorno de Colombia
filter(str_detect(place, regex("Colombia", ignore_case = TRUE))) %>%
# Filtro temporal: últimos 20 años a partir de la fecha más reciente del catálogo
filter(fecha >= (max(fecha, na.rm = TRUE) - years(20)))
# Si el locale español no está disponible, usar mes numérico como respaldo
if (all(is.na(sismos$mes))) {
sismos <- sismos %>% mutate(mes = factor(month(time), levels = 1:12))
}
n_total <- nrow(sismos)
rango_fechas <- range(sismos$fecha, na.rm = TRUE)
El conjunto de datos filtrado contiene 584 eventos sísmicos registrados en Colombia entre 20/08/2006 y 10/08/2026.
Nota metodológica: el catálogo fuente corresponde a un umbral mínimo de magnitud (aprox. M 4.5), por lo que este informe describe la sismicidad moderada a mayor, no la totalidad de la actividad sísmica del país (la cual incluye miles de eventos menores registrados por la Red Sismológica Nacional).
Se clasifican los eventos según rangos estándar de magnitud (escala de momento/Richter):
sismos <- sismos %>%
mutate(
rango_mag = cut(
mag,
breaks = c(4.5, 5, 6, 7, 8, Inf),
labels = c("Leve (4.5-4.9)", "Moderado (5.0-5.9)",
"Fuerte (6.0-6.9)", "Mayor (7.0-7.9)", "Gran sismo (8.0+)"),
right = FALSE, include.lowest = TRUE
)
)
tabla_mag <- sismos %>%
count(rango_mag, name = "n_eventos") %>%
mutate(porcentaje = round(100 * n_eventos / sum(n_eventos), 1))
kable(tabla_mag, col.names = c("Rango de magnitud", "N° de eventos", "% del total"),
caption = "Distribución de sismos por rango de magnitud") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
| Rango de magnitud | N° de eventos | % del total |
|---|---|---|
| Leve (4.5-4.9) | 481 | 82.4 |
| Moderado (5.0-5.9) | 94 | 16.1 |
| Fuerte (6.0-6.9) | 7 | 1.2 |
| Mayor (7.0-7.9) | 2 | 0.3 |
p1 <- ggplot(sismos, aes(x = rango_mag, fill = rango_mag)) +
geom_bar() +
scale_fill_viridis_d(option = "magma", begin = 0.15, end = 0.85) +
labs(title = "Sismos por rango de magnitud", x = "Rango de magnitud", y = "N° de eventos") +
theme_minimal(base_size = 12) +
theme(legend.position = "none", axis.text.x = element_text(angle = 20, hjust = 1))
ggplotly(p1)
La profundidad se clasifica según los rangos estándar de sismología (USGS):
sismos <- sismos %>%
mutate(
rango_prof = cut(
depth,
breaks = c(0, 70, 300, 700, Inf),
labels = c("Superficial (0-70 km)", "Intermedio (70-300 km)",
"Profundo (300-700 km)", "Muy profundo (>700 km)"),
right = TRUE, include.lowest = TRUE
)
)
tabla_prof <- sismos %>%
count(rango_prof, name = "n_eventos") %>%
mutate(porcentaje = round(100 * n_eventos / sum(n_eventos), 1))
kable(tabla_prof, col.names = c("Rango de profundidad", "N° de eventos", "% del total"),
caption = "Distribución de sismos por rango de profundidad") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
| Rango de profundidad | N° de eventos | % del total |
|---|---|---|
| Superficial (0-70 km) | 266 | 45.5 |
| Intermedio (70-300 km) | 317 | 54.3 |
| Profundo (300-700 km) | 1 | 0.2 |
p2 <- ggplot(sismos, aes(x = rango_prof, fill = rango_prof)) +
geom_bar() +
scale_fill_viridis_d(option = "viridis", begin = 0.15, end = 0.85) +
labs(title = "Sismos por rango de profundidad", x = "Rango de profundidad", y = "N° de eventos") +
theme_minimal(base_size = 12) +
theme(legend.position = "none", axis.text.x = element_text(angle = 20, hjust = 1))
ggplotly(p2)
p3 <- ggplot(sismos, aes(x = depth, y = mag, color = rango_mag,
text = paste0("Lugar: ", place, "<br>Fecha: ", fecha))) +
geom_point(alpha = 0.7, size = 2) +
scale_color_viridis_d(option = "magma", begin = 0.15, end = 0.85) +
labs(title = "Relación entre magnitud y profundidad",
x = "Profundidad (km)", y = "Magnitud", color = "Rango magnitud") +
theme_minimal(base_size = 12)
ggplotly(p3, tooltip = "text")
Este cruce permite identificar si los sismos de mayor magnitud tienden a concentrarse en profundidades superficiales (generalmente más destructivos por su cercanía a la superficie) o en profundidades intermedias/profundas (asociadas a la subducción de placas).
tabla_cruz <- sismos %>%
count(rango_mag, rango_prof) %>%
pivot_wider(names_from = rango_prof, values_from = n, values_fill = 0)
kable(tabla_cruz, caption = "N° de eventos por rango de magnitud y profundidad") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
| rango_mag | Superficial (0-70 km) | Intermedio (70-300 km) | Profundo (300-700 km) |
|---|---|---|---|
| Leve (4.5-4.9) | 203 | 278 | 0 |
| Moderado (5.0-5.9) | 59 | 34 | 1 |
| Fuerte (6.0-6.9) | 4 | 3 | 0 |
| Mayor (7.0-7.9) | 0 | 2 | 0 |
Se calcula el intervalo (en días) entre eventos consecutivos dentro de cada rango de magnitud, lo cual indica cada cuánto tiempo ocurre, en promedio, un sismo de determinada intensidad.
intervalos <- sismos %>%
arrange(rango_mag, time) %>%
group_by(rango_mag) %>%
mutate(dias_desde_anterior = as.numeric(difftime(time, lag(time), units = "days"))) %>%
summarise(
n_eventos = n(),
intervalo_prom_dias = round(mean(dias_desde_anterior, na.rm = TRUE), 1),
intervalo_mediana_dias = round(median(dias_desde_anterior, na.rm = TRUE), 1),
.groups = "drop"
)
kable(intervalos,
col.names = c("Rango de magnitud", "N° eventos", "Intervalo promedio (días)", "Intervalo mediana (días)"),
caption = "Frecuencia de ocurrencia según intensidad") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
| Rango de magnitud | N° eventos | Intervalo promedio (días) | Intervalo mediana (días) |
|---|---|---|---|
| Leve (4.5-4.9) | 481 | 15.2 | 10.2 |
| Moderado (5.0-5.9) | 94 | 76.7 | 48.8 |
| Fuerte (6.0-6.9) | 7 | 750.3 | 710.1 |
| Mayor (7.0-7.9) | 2 | 5061.8 | 5061.8 |
p4 <- ggplot(intervalos, aes(x = rango_mag, y = intervalo_prom_dias, fill = rango_mag)) +
geom_col() +
scale_fill_viridis_d(option = "magma", begin = 0.15, end = 0.85) +
labs(title = "Días promedio entre sismos según su intensidad",
x = "Rango de magnitud", y = "Intervalo promedio (días)") +
theme_minimal(base_size = 12) +
theme(legend.position = "none", axis.text.x = element_text(angle = 20, hjust = 1))
ggplotly(p4)
serie_anual <- sismos %>%
count(anio, name = "n_eventos")
p5 <- ggplot(serie_anual, aes(x = anio, y = n_eventos)) +
geom_col(fill = "#2c3e50") +
geom_smooth(method = "loess", se = FALSE, color = "#e74c3c", linewidth = 1) +
labs(title = "Serie de tiempo anual de sismos en Colombia",
x = "Año", y = "N° de eventos") +
scale_x_continuous(breaks = scales::pretty_breaks(n = 10)) +
theme_minimal(base_size = 12)
ggplotly(p5)
serie_anual_mag <- sismos %>%
count(anio, rango_mag, name = "n_eventos")
p6 <- ggplot(serie_anual_mag, aes(x = anio, y = n_eventos, fill = rango_mag)) +
geom_col(position = "stack") +
scale_fill_viridis_d(option = "magma", begin = 0.15, end = 0.85) +
labs(title = "Sismos por año, desagregados por rango de magnitud",
x = "Año", y = "N° de eventos", fill = "Rango magnitud") +
scale_x_continuous(breaks = scales::pretty_breaks(n = 10)) +
theme_minimal(base_size = 12)
ggplotly(p6)
heat_data <- sismos %>%
count(anio, mes, name = "n_eventos")
p7 <- ggplot(heat_data, aes(x = mes, y = factor(anio), fill = n_eventos)) +
geom_tile(color = "white") +
scale_fill_viridis_c(option = "inferno", direction = -1) +
labs(title = "Distribución mensual de sismos por año",
x = "Mes", y = "Año", fill = "N° eventos") +
theme_minimal(base_size = 11) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
ggplotly(p7)
Este análisis permite identificar si existen periodos del año o años específicos con mayor concentración de actividad sísmica, útil para la planeación de simulacros y campañas de prevención.
paleta <- colorFactor(viridis::viridis(5), domain = sismos$rango_mag)
leaflet(sismos) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addCircleMarkers(
lng = ~longitude, lat = ~latitude,
radius = ~ifelse(mag < 5, 4, ifelse(mag < 6, 6, ifelse(mag < 7, 9, 13))),
color = ~paleta(rango_mag),
stroke = FALSE, fillOpacity = 0.7,
popup = ~paste0("<b>", place, "</b><br>Fecha: ", fecha,
"<br>Magnitud: ", mag, "<br>Profundidad: ", depth, " km")
) %>%
addLegend("bottomright", pal = paleta, values = ~rango_mag, title = "Rango de magnitud") %>%
addFullscreenControl()
leaflet(sismos) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addHeatmap(lng = ~longitude, lat = ~latitude, intensity = ~mag,
blur = 20, max = 0.05, radius = 15)
Se extrae la localidad de referencia a partir del campo
place (texto del catálogo) para identificar las zonas más
recurrentes.
sismos <- sismos %>%
mutate(
localidad = str_trim(str_remove(place, "^[0-9]+\\s*km\\s+[A-Z]+\\s+of\\s+")),
localidad = str_remove(localidad, ",\\s*Colombia.*$")
)
top_zonas <- sismos %>%
count(localidad, name = "n_eventos", sort = TRUE) %>%
slice_head(n = 15)
kable(top_zonas, col.names = c("Localidad / zona de referencia", "N° de eventos"),
caption = "Top 15 zonas con mayor frecuencia de sismos") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
| Localidad / zona de referencia | N° de eventos |
|---|---|
| Cepitá | 117 |
| Jordán | 48 |
| Nuquí | 26 |
| Aratoca | 20 |
| Riosucio | 16 |
| Bahía Solano | 11 |
| Cubará | 10 |
| Piedecuesta | 10 |
| Murindó | 9 |
| northern Colombia | 8 |
| Colombia | 7 |
| Lejanías | 7 |
| Mesetas | 7 |
| Pizarro | 7 |
| Puerto Gaitán | 7 |
p8 <- ggplot(top_zonas, aes(x = reorder(localidad, n_eventos), y = n_eventos)) +
geom_col(fill = "#c0392b") +
coord_flip() +
labs(title = "Zonas con mayor frecuencia sísmica",
x = NULL, y = "N° de eventos") +
theme_minimal(base_size = 11)
ggplotly(p8)
bins_geo <- sismos %>%
mutate(
lat_bin = round(latitude / 0.5) * 0.5,
lon_bin = round(longitude / 0.5) * 0.5
) %>%
count(lat_bin, lon_bin, name = "n_eventos")
p9 <- ggplot(bins_geo, aes(x = lon_bin, y = lat_bin, fill = n_eventos)) +
geom_tile() +
scale_fill_viridis_c(option = "inferno", direction = -1) +
coord_fixed(1.1) +
labs(title = "Concentración geográfica de sismos (cuadrícula 0.5°)",
x = "Longitud", y = "Latitud", fill = "N° eventos") +
theme_minimal(base_size = 11)
ggplotly(p9)
Antes de interpretar las cifras del catálogo, conviene explicar el fenómeno físico que las origina.
El motor: tectónica de placas. La litósfera terrestre está fragmentada en placas rígidas que flotan sobre el manto, una capa parcialmente dúctil que se mueve muy lentamente por corrientes de convección térmica. Estas placas se desplazan entre sí unos pocos centímetros al año, sinembargo lo hacen de forma continua durante millones de años, acumulando y liberando cantidades enormes de energía.(Bucaramanga, 2026)
Colombia se encuentra en uno de los puntos de mayor complejidad tectónica del planeta, en la confluencia de tres placas principales:
A esta interacción de placas se suman las fallas geológicas corticales activas dentro del propio territorio —como los sistemas de Romeral, Bucaramanga-Santa Marta, Cauca-Almaguer y Frontal Llanero, entre otros—, que generan sismicidad superficial independiente de la subducción.
El mecanismo físico: rebote elástico. Un sismo no es más que la liberación súbita de energía de deformación acumulada en las rocas. Mientras dos bloques de corteza están en contacto a lo largo de una falla, la fricción los mantiene “trabados” mientras las placas siguen moviéndose; la roca se deforma elásticamente, como un resorte que se comprime. Cuando el esfuerzo acumulado supera la resistencia por fricción de la falla, esta se rompe abruptamente, los bloques se desplazan de golpe hasta una nueva posición de equilibrio, y la energía almacenada se libera en forma de ondas sísmicas que viajan por la Tierra y se perciben como el temblor. Este proceso se conoce como teoría del rebote elástico
Esto explica varios patrones observados en los datos de este informe:
Para esto se distinguen dos conceptos:
2.1. El proceso de ruptura es un sistema caótico y no lineal. El momento exacto en que una falla cede depende de innumerables factores microscópicos (rugosidad de la roca, presión de fluidos, distribución heterogénea del esfuerzo) que no pueden medirse con la resolución necesaria. Pequeñas diferencias iniciales producen resultados completamente distintos, igual que ocurre con la atmósfera y el clima a corto plazo.
2.2 No existen precursores confiables. Se han investigado numerosos posibles “avisos” (cambios en niveles freáticos, gases radón, comportamiento animal, sismos pequeños previos), pero ninguno se cumple de forma consistente antes de todos los sismos ni está ausente en su totalidad cuando no hay sismo; es decir, generan demasiados falsos positivos y falsos negativos para ser útiles operativamente.
2.3. La energía se acumula en el interior de la Tierra, fuera de nuestro alcance de observación directa. No es posible “ver” ni medir directamente el estado de esfuerzo de una falla a 10-100 km de profundidad; solo se infiere indirectamente (GPS, sismicidad histórica, deformación superficial), con márgenes de incertidumbre demasiado grandes para una predicción puntual.
2.4. El mismo segmento de falla no se comporta de forma perfectamente periódica. Aunque existe un concepto de “ciclo sísmico” (acumulación y liberación repetida de esfuerzo), los intervalos entre grandes sismos en una misma falla varían de forma significativa y no siguen un reloj fijo, como sugiere también la variabilidad observada en los intervalos calculados en el Capítulo 2 de este informe.
(Colombiano, 2026;Martins, 2026)
Uniendo el marco conceptual anterior con los hallazgos descriptivos de los capítulos 1 a 3:
resumen <- sismos %>%
summarise(
n_total = n(),
mag_promedio = round(mean(mag), 2),
mag_max = max(mag),
prof_promedio = round(mean(depth), 1),
zona_top = top_zonas$localidad[1]
)
cat("
1. **Priorizar la actualización de microzonificación sísmica** en las localidades identificadas como de mayor frecuencia de eventos, especialmente aquellas con sismos superficiales (< 70 km), por su mayor potencial de daño.
2. **Fortalecer los protocolos de respuesta y simulacros** en los periodos del año y años que históricamente concentran mayor actividad, según lo evidenciado en el mapa de calor mensual.
3. **Reforzar la normativa de construcción sismorresistente (NSR-10 o la vigente)** en los municipios ubicados dentro de las zonas de mayor concentración geográfica identificadas en el Capítulo 3.
4. **Mantener y ampliar la red de monitoreo sismológico**, dado que gran parte de los eventos registrados corresponde a magnitudes moderadas que pueden pasar desapercibidas sin instrumentación adecuada.
5. **Incorporar este tipo de análisis descriptivo de forma periódica** (anual o semestral) como insumo para los planes de gestión del riesgo de desastres a nivel municipal y departamental.
6. **Profundizar el análisis** incorporando datos de intensidad percibida (escala Mercalli), población expuesta y vulnerabilidad de infraestructura, para pasar de un enfoque descriptivo a uno de gestión prospectiva del riesgo.
")
-Bucaramanga, C. (2026, 27 mayo). ¿Qué es un sismo y por qué ocurre? Una explicación sobre el movimiento de la Tierra y los terremotos. UDES Bucaramanga. https://bucaramanga.udes.edu.co/extension/noticias/que-es-un-sismo-y-por-que-ocurre-una-explicacion-sobre-el-movimiento-de-la-tierra-y-los-terremotos
-Colombiano, E. (2026, 10 agosto). Por qué la ciencia todavía no es capaz de predecir terremotos | El Colombiano. El Colombiano. https://www.elcolombiano.com/tecnologia/ciencia/prediccion-terremotos-explicacion-GK39773577
-Ingrassia, V. (2026, 26 agosto). Terremotos sin fin: por qué la región tiembla tanto y qué explica la repetición de sismos recientes. Infobae. https://www.infobae.com/america/ciencia-america/2026/08/26/estamos-monitoreando-en-tiempo-real-que-dicen-los-expertos-sobre-la-seguidilla-de-terremotos-en-america-latina/
-Martins, A. (2026, 12 agosto). ¿Por qué es imposible predecir el momento preciso de un terremoto? BBC News Mundo. https://www.bbc.com/mundo/articles/c62edvvy7d9o
Informe generado automáticamente en R Markdown. Fuente de datos: catálogo sísmico (formato USGS) proporcionado por el usuario.