Vamos a leer los circuitos de la provincia y las seccionales de Santa Fe
circuitos_stafe<- read_sf("data/circuito_21.shp")
seccionales <- read_xlsx("data/lacapital+rosario_circuitos_seccionales.xlsx")%>%
mutate(across(where(is.character), toupper))
Dividimos la columna de circuito por la de circuito 2025 y nombre de circuito anterior.
# Primero creamos la columna de circuitos anteriores
circuitos_stafe <- circuitos_stafe %>%
mutate(
circuito_anterior = str_extract(circuito, "(?<=\\()([^)]+)(?=\\))") %>%
str_remove_all("ex|\\s") %>% # elimina "ex" y espacios
str_remove("^0+") %>% # elimina ceros iniciales
str_trim()
)
#limpiamos y renombramos "circuito"
circuitos_stafe <- circuitos_stafe %>%
mutate(
# Primero creamos circuito_2025
circuito_2025_id = str_remove(circuito, "\\(.*\\)"), # elimina contenido entre ()
circuito_2025_id = str_remove_all(circuito_2025_id, "\\s+"), # elimina espacios
circuito_2025_id = str_remove(circuito_2025_id, "^0+")) %>% # elimina ceros iniciales
select( -circuito)
glimpse(circuitos_stafe)
## Rows: 556
## Columns: 10
## $ gid <int> 11296, 11321, 11324, 11332, 11346, 11348, 11357, 113…
## $ distrito <chr> "21", "21", "21", "21", "21", "21", "21", "21", "21"…
## $ provincia <chr> "Santa Fe", "Santa Fe", "Santa Fe", "Santa Fe", "San…
## $ departamen <chr> "General Obligado", "San Cristobal", "9 de Julio", "…
## $ cabecera <chr> "Las Toscas", "Soledad", "Esteban Rams", "Aguara", "…
## $ indec_p <chr> "82", "82", "82", "82", "82", "82", "82", "82", "82"…
## $ indec_d <chr> "049", "091", "077", "091", "077", "133", "112", "09…
## $ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((-59.09564 -..., MULTIPO…
## $ circuito_anterior <chr> "235", "195", "283", "177", "284", "260", "208C", "2…
## $ circuito_2025_id <chr> "2350", "1950", "2830", "1770", "2840", "2600", "208…
Vamos a agregar una columna con las seccionales de SFC y ROS
# Convertir a character en circuitos_stafe
circuitos_stafe <- circuitos_stafe %>%
mutate(circuito_2025_id = as.character(circuito_2025_id))
# Convertir a character en seccionales
seccionales <- seccionales %>%
mutate(circuito_2025_id = as.character(circuito_2025_id))
circuitos_stafe <- circuitos_stafe %>%
left_join(seccionales %>%
select(circuito_2025_nombre, circuito_2025_id, seccional),
by = "circuito_2025_id")
library(sf)
library(dplyr)
# 1. Asegurarte de que todo está en un CRS proyectado temporalmente
circuitos_stafe <- circuitos_stafe %>%
st_make_valid() %>% # repara geometrías rotas
st_buffer(0) %>% # corrige pequeños huecos o overlaps
st_transform(3857) # usa metros para operaciones geométricas
# 2. Agrupar por seccional (disolver polígonos)
seccionales_agrupadas <- circuitos_stafe %>%
group_by(seccional) %>%
summarise(do_union = TRUE) %>%
st_make_valid() %>%
st_transform(4326) # volvemos a WGS84 para Leaflet
# 3. Calcular centroides seguros dentro del polígono
centroides <- seccionales_agrupadas %>%
st_point_on_surface() %>% # siempre dentro del polígono
st_transform(4326)
## Warning: st_point_on_surface assumes attributes are constant over geometries
## Warning in st_point_on_surface.sfc(st_geometry(x)): st_point_on_surface may not
## give correct results for longitude/latitude data
# 3. Crear el mapa interactivo con Leaflet
mapa_interactivo <- leaflet(seccionales_agrupadas) %>%
# Añadir el mapa base Stamen Toner (blanco y negro con calles)
addProviderTiles(providers$Stadia.StamenToner) %>%
# Añadir polígonos de seccionales con colores menos transparentes
addPolygons(
fillColor = ~colorFactor("Set3", seccional)(seccional), # Paleta de colores
fillOpacity = 0.85, # Opacidad del relleno (mucho menos transparente)
color = "white", # Color del borde
weight = 2, # Grosor del borde
opacity = 1, # Opacidad del borde
smoothFactor = 0.5,
label = ~seccional, # Etiqueta al pasar el cursor
labelOptions = labelOptions(direction = "auto")
) %>%
# Añadir etiquetas permanentes con los nombres de las seccionales
addLabelOnlyMarkers(
data = centroides,
label = ~seccional,
labelOptions = labelOptions(
noHide = TRUE, # Hace las etiquetas permanentes
direction = "center",
textOnly = TRUE,
style = list(
"color" = "black",
"font-weight" = "bold",
"font-size" = "12px",
"text-shadow" = "1px 1px 3px white" # Para mejor legibilidad
)
)
)
## Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set3 is 12
## Returning the palette you asked for with that many colors
saveWidget(
widget = mapa_interactivo,
file = "mapa_interactivo.html",
selfcontained = TRUE, # <-- empaqueta JS/CSS dentro del HTML
title = "Mapa interactivo",
background = "white"
)
# Mostrar el mapa
mapa_interactivo