Mapas y visualización de datos geoespaciales en R con {sf}
18/11/2025
341 visitasR cuenta con un muy amplio
ecosistema de paquetes para datos geoespaciales. Uno de los
paquetes más importantes es {sf}, que permite manipular datos espaciales a partir del estándar simple features (características simples), ampliamente utilizado en sistemas de información geográfica (SIG/GIS).
En esta guía iré guardando los comandos que uso frecuentemente para manipular, transformar y visualizar datos geoespaciales en R. En la medida que voy aprendiendo más sobre hacer mapitas, iré actualizando y complementando.
Lo inicial es instalar {sf}:
install.packages("sf")
Y cargarlo junto a {dplyr} para empezar a trabajar con datos geoespaciales.
library(sf)
library(dplyr)
Nota: para simplificar, en este tutorial voy a ocultar el código de los gráficos, pero siempre estará disponible bajo flechitas que despliegan el código, como la siguiente:
Ver código para los gráficos
library(ggplot2)
# tema de colores
thematic::thematic_on(fg = "#553A74",
bg = "#EAD2FA",
accent = "#9069C0")
theme_set(
# fondo transparente para mapas
theme(plot.background = element_rect(fill = "transparent", color = "transparent")) +
# borrar líneas feas
theme(axis.ticks = element_blank())
)
Índice
Carga de mapas
Una de las fuentes principales de datos geoespaciales son los shapefiles. Pero también existen paquetes de R que contienen información geoespacial, para mayor conveniencia. Exploraremos ambas opciones a continuación.
Cargar mapas de cualquier país
Si no tenemos o no queremos descargar shapes, podemos cargar mapas de cualquier país directo en R gracias a
{rnaturalearth}. Con este paquete obtenemos directamente mapas de cualquier país del mundo, incluyendo sus estados o regiones internos, sin necesidad de descargas.
Instala {rnaturalearth} si no lo tienes:
install.packages("rnaturalearth")
Puedes insertar el nombre de tu país para seguir con este tutorial usando ejemplos de tu territorio.
library(rnaturalearth)
pais <- ne_states("Argentina")
# pais <- ne_states("Mexico")
# pais <- ne_states("Colombia")
mapa <- pais |>
# seleccionar columnas
select(pais = admin,
region = name_es,
geometry)
mapa
Simple feature collection with 24 features and 2 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -73.57274 ymin: -55.05202 xmax: -53.66155 ymax: -21.78694
Geodetic CRS: WGS 84
First 10 features:
pais region geometry
1 Argentina Entre Ríos MULTIPOLYGON (((-58.20011 -...
12 Argentina Salta MULTIPOLYGON (((-68.49647 -...
13 Argentina Jujuy MULTIPOLYGON (((-67.25133 -...
741 Argentina Formosa MULTIPOLYGON (((-62.34136 -...
746 Argentina Misiones MULTIPOLYGON (((-54.66497 -...
749 Argentina Chaco MULTIPOLYGON (((-58.35127 -...
750 Argentina Corrientes MULTIPOLYGON (((-58.6042 -2...
1318 Argentina Catamarca MULTIPOLYGON (((-68.33776 -...
1320 Argentina La Rioja MULTIPOLYGON (((-69.65405 -...
1321 Argentina San Juan MULTIPOLYGON (((-69.95766 -...
Cargar shapes
Un shapefile es un formato de archivo común para datos geoespaciales, que en realidad consiste en una carpeta con archivos relacionados (.shp, .shx, .dbf, entre otros) que juntos representan la geometría y atributos de los objetos geográficos.
Teniendo la carpeta, basta con cargarla con la función read_sf().
Ejemplo de descarga y carga de un shapefile de Chile
Para aprender, podemos descargar un shape y usarlo para practicar. Si no tienes uno a mano, en el siguiente botón podemos bajar un shapefile de Chile por regiones, que proviene de la Mapoteca de la Biblioteca del Congreso Nacional.
También puedes descargarlo directamente desde R con download.file() y luego unzip(),
como se indica en este post.
Una vez descargado, descomprimimos el archivo y obtenemos una carpeta. Esta carpeta es nuestro shapefile, así que la guardamos dentro de nuestro proyecto de RStudio, idealmente dentro de una carpeta donde guardemos nuestros mapas.
# descargar
download.file("https://www.bcn.cl/obtienearchivo?id=repositorio/10221/10398/2/Regiones.zip",
"Regiones.zip")
# descomprimir
unzip("Regiones.zip", exdir = "shapes/Regiones")
En el siguiente ejemplo, guardamos el shapefile en una carpeta shapes, y lo cargamos con read_sf().
mapa <- read_sf("shapes/Regiones") |>
janitor::clean_names()
mapa
Simple feature collection with 17 features and 7 fields
Geometry type: GEOMETRY
Dimension: XY
Bounding box: xmin: -12183900 ymin: -7554306 xmax: -7393644 ymax: -1978920
Projected CRS: WGS 84 / Pseudo-Mercator
# A tibble: 17 × 8
objectid cir_sena codregion area_km st_area_sh st_length region
* <dbl> <int> <int> <dbl> <dbl> <dbl> <chr>
1 1084 1 15 16867. 18868687744. 750530. Región de Arica …
2 1085 2 1 42285. 48306372203. 1213713. Región de Tarapa…
3 1086 3 2 126071. 150845155633 2516112. Región de Antofa…
4 1087 15 12 133053. 358131609833 90498304. Región de Magall…
5 1088 14 11 106703. 224274263072 41444811. Región de Aysén …
6 1089 4 3 75661. 96439063562. 2401741. Región de Atacama
7 1090 5 4 40576. 54980818749. 2065933. Región de Coquim…
8 1091 6 5 16323. 23014748571. 1679609. Región de Valpar…
9 1092 7 13 15392. 22252038246. 1064253. Región Metropoli…
10 1093 13 10 48408. 87718341940. 7874158. Región de Los La…
11 1094 12 14 18245. 31086613540. 1844423. Región de Los Rí…
12 1095 11 9 31838. 52215073344. 1501025. Región de La Ara…
13 1096 10 8 24022. 38176117509. 2097147. Región del Bío-B…
14 1097 10 16 13104. 20376298459. 1074094. Región de Ñuble
15 1098 9 7 30322. 45969426092. 1388328. Región del Maule
16 1099 8 6 16349. 24090278437. 984853. Región del Liber…
17 1100 0 0 3937. 9306245194. 388722. Zona sin demarcar
# ℹ 1 more variable: geometry <GEOMETRY [m]>
Como vemos, una vez que cargamos los datos geoespaciales obtenemos una tabla con características especiales. Arriba de la tabla vemos una descripción de las características del mapa, el tipo de geometrías, la caja o bounding box que enmarca los polígonos, y el sistema de referencia de coordenadas del mapa.
En {sf} los datos geoespaciales además contienen una columna geometry, que contiene las geometrías (puntos, líneas o polígonos) que definen la forma y ubicación de los elementos geográficos. Vamos a trabajar con esta columna si queremos modificar la geometría de los elementos geoespaciales o calcular algo a partir de ellos. Cada fila de la tabla representa un objeto geográfico (una región, comuna, país, etc.) y las demás columnas son variables relacionadas al objeto geográfico (población, superficie, nombre, etc.)
Visualización básica de mapas
Para visualizar un mapa con {sf} usamos la geometría geom_sf() dentro de un gráfico de {ggplot2}. Esta función reconoce automáticamente la columna geometry del objeto espacial, y dibuja las formas geográficas correspondientes.
mapa |>
ggplot() +
geom_sf(fill = "#9069C0",
color = "#EBD2FA",
linewidth = 0.1)
Operaciones sobre geometrías
Las operaciones sobre geometrías permiten manipular y analizar las formas y ubicaciones de los objetos geográficos. A continuación veremos algunas operaciones comunes que se pueden realizar con el paquete {sf} en R.
Calcular centroide
El centroide es el punto central de un polígono. Calcularlo sirve, por ejemplo, para ubicar una etiqueta de texto sobre un polígono, poner un punto sobre un territorio que crece con respecto a una variable, etc.
mapa_centroide <- mapa |>
select(region, geometry) |>
mutate(centroide = st_centroid(geometry))
region centroide
1 Entre Ríos POINT (-59.20493 -32.03189)
12 Salta POINT (-64.80661 -24.28824)
13 Jujuy POINT (-65.77985 -23.31783)
741 Formosa POINT (-59.94839 -24.89604)
746 Misiones POINT (-54.65212 -26.86956)
749 Chaco POINT (-60.77109 -26.39039)
750 Corrientes POINT (-57.79471 -28.76018)
1318 Catamarca POINT (-66.99006 -27.3092)
1320 La Rioja POINT (-67.21371 -29.66235)
1321 San Juan POINT (-68.88199 -30.82274)
1323 Mendoza POINT (-68.60826 -34.58944)
1328 Neuquén POINT (-70.11374 -38.62865)
1333 Chubut POINT (-68.51499 -43.78523)
1335 Río Negro POINT (-67.21765 -40.40738)
1337 Santa Cruz POINT (-69.8981 -48.76187)
1339 Tierra del Fuego POINT (-67.4401 -54.32625)
1726 Buenos Aires POINT (-60.54573 -36.66279)
1746 Buenos Aires POINT (-58.45093 -34.64272)
3852 Santa Fe POINT (-60.93513 -30.66904)
3853 Tucumán POINT (-65.36557 -26.9491)
3854 Santiago del Estero POINT (-63.2909 -27.71835)
3855 San Luis POINT (-66.03363 -33.74238)
3856 La Pampa POINT (-65.44562 -37.12691)
3857 Córdoba POINT (-63.76859 -32.07319)
Ver código del gráfico
mapa_centroide |>
filter(region == mapa$region[3]) |>
ggplot() +
geom_sf(fill = "#9069C0",
linewidth = NA) +
geom_sf(
aes(geometry = centroide),
size = 3, alpha = .6) +
geom_sf_text(
aes(geometry = centroide),
label = "centroide", size = 3,
vjust = 2)
Extraer longitud y latitud
Para obtener las coordenadas (longitud y latitud) de un elemento espacial, necesitamos primero que sea un punto, porque un polígono es una figura compleja que no tiene solamente una latitud y una longitud. Si tenemos un polígono,
primero calculamos el centroide, y luego extraemos las coordenadas con st_coordinates(). Como esta función retorna la longitud y latitud de cada punto al mismo tiempo, tenemos que pedirle que entregue la una o la otra usando corchetes.
mapa_centroide_coordenadas <- mapa_centroide |>
mutate(lon = st_coordinates(centroide)[,1],
lat = st_coordinates(centroide)[,2])
region lon lat
1 Entre Ríos -59.20493 -32.03189
12 Salta -64.80661 -24.28824
13 Jujuy -65.77985 -23.31783
741 Formosa -59.94839 -24.89604
746 Misiones -54.65212 -26.86956
749 Chaco -60.77109 -26.39039
750 Corrientes -57.79471 -28.76018
1318 Catamarca -66.99006 -27.30920
1320 La Rioja -67.21371 -29.66235
1321 San Juan -68.88199 -30.82274
1323 Mendoza -68.60826 -34.58944
1328 Neuquén -70.11374 -38.62865
1333 Chubut -68.51499 -43.78523
1335 Río Negro -67.21765 -40.40738
1337 Santa Cruz -69.89810 -48.76187
1339 Tierra del Fuego -67.44010 -54.32625
1726 Buenos Aires -60.54573 -36.66279
1746 Buenos Aires -58.45093 -34.64272
3852 Santa Fe -60.93513 -30.66904
3853 Tucumán -65.36557 -26.94910
3854 Santiago del Estero -63.29090 -27.71835
3855 San Luis -66.03363 -33.74238
3856 La Pampa -65.44562 -37.12691
3857 Córdoba -63.76859 -32.07319
Ver código del gráfico
mapa_centroide_coordenadas |>
distinct(region, .keep_all = TRUE) |>
mutate(region = forcats::fct_reorder(region, lat)) |> # ordenar regiones
ggplot() +
aes(lat, region) +
geom_col(width = 0.7,
fill = "#9069C0") +
geom_text(aes(label = region),
size = 3, hjust = -0.05, color = "#EAD2FA") +
scale_y_discrete(labels = NULL) +
labs(y = NULL, x = "Latitud")
Calcular buffer
Un buffer es una zona alrededor de un objeto geográfico, definida por una distancia específica. Calcular un buffer es útil para analizar áreas de influencia, proximidad a ciertos puntos o regiones, o para hacer modificiones sobre mapas con fines de visualización.
Con la función st_buffer() definimos el espacio en torno a un polígono, especificando en el argumento dist la distancia del buffer en las unidades del sistema de coordenadas del mapa (por ejemplo, metros si el mapa está en UTM), y con max_cells podemos controlar la calidad del polígono resultante.
mapa_buffer <- mapa |>
# filtrar una región/polígono
filter(region == mapa$region[3]) |>
# crear buffer
mutate(buffer = st_buffer(geometry,
dist = 20000,
max_cells = 10000))
Ver código del gráfico
mapa_buffer |>
ggplot() +
# capa de la región
geom_sf(aes(geometry = geometry),
fill = "#9069C0", linewidth = NA) +
# capa del buffer
geom_sf(aes(geometry = buffer),
fill = "#9069C0", alpha = 0.5, linewidth = NA)
Calcular caja de un polígono
Con la función st_bbox() obtenemos las coordenadas de la caja que envuelve a un polígono o conjunto de polígonos. Esta caja está definida por las coordenadas mínimas y máximas en los ejes x (longitud) e y (latitud).
caja <- st_bbox(mapa)
caja
xmin ymin xmax ymax
-73.57274 -55.05202 -53.66155 -21.78694
Convertir caja a polígono
Teniendo una caja con sus coordenadas, podemos convertirla a un polígono para aplicarlo sobre (o debajo de) un mapa.
rectangulo <- caja |>
st_as_sfc(crs = st_crs(mapa))
Ver código del gráfico
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#EBD2FB",
linewidth = 0.1) +
# capa con la caja encima
geom_sf(data = rectangulo,
fill = "#9069C0", color = "#9069C0",
linewidth = 0.8, alpha = 0.4) +
# tema
theme(axis.text = element_blank(),
panel.background = element_blank())
Poner un punto en un mapa
Si queremos poner puntos en posiciones específicas de un mapa, sólo necesitamos crear una tabla con las coordenadas de los puntos y convertir la tabla a sf con st_as_sf(). Al hacer esto, es necesario especificar el sistema de referencia de coordenadas (CRS) del mapa, para que los puntos se ubiquen correctamente. Hacemos esto extrayendo el CRS del mapa con st_crs() y aplicándolo a nuestra nueva tabla sf.
# definir coordenadas
coordenadas <- tibble(longitud = -70,
latitud = -38)
# convertir tabla a sf
punto <- coordenadas |>
st_as_sf(coords = c("longitud", "latitud"),
crs = st_crs(mapa))
Ver código del gráfico
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#EBD2FB",
linewidth = 0.1) +
# capa con el punto
geom_sf(data = punto,
size = 3, alpha = .5)
Poner varios puntos en un mapa
Si necesitamos agregar más de un punto, simplemente hacemos una tabla con todos los que necesitemos. Obviamente también podemos especificar otras columnas que podemos usar para etiquetar los puntos, especificar sus colores, y más.
coordenadas <- tribble(~nombre, ~lon, ~lat, ~n,
"A", -69, -38, 4,
"B", -65, -37, 6,
"C", -61, -36, 9)
puntos <- coordenadas |>
# convertir tabla a sf
st_as_sf(coords = c("lon", "lat"),
crs = st_crs(mapa))
Ver código del gráfico
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#EBD2FB",
linewidth = 0.1) +
# capa con puntos
geom_sf(data = puntos,
aes(size = n),
alpha = .5) +
# capa con textos
geom_sf_label(data = puntos,
aes(label = nombre),
size = 3, vjust = -0.8,
fontface = "bold") +
# escala de tamaño
scale_size(range = c(3, 6),
breaks = scales::breaks_pretty(n = 3)) +
guides(size = guide_legend(override.aes = list(color = "#9069C0",
alpha = 1)))
Crear un cuadrado
Para poner un cuadrado encima de una ubicación del mapa, primero creamos un punto, luego lo
expandimos con un buffer, calculamos
la caja que envuelve a dicho punto, y finalmente convertimos la caja en un polígono sf.
coordenadas <- tibble(longitud = -58, latitud = -38)
punto <- coordenadas |>
# convertir tabla a sf
st_as_sf(coords = c("longitud", "latitud"),
crs = st_crs(mapa))
cuadrado <- punto |>
st_buffer(dist = 100000) |> # agrandar punto
st_bbox() |> # crear caja al rededor
st_as_sfc(crs = st_crs(mapa)) # convertir a sf
Ver código del gráfico
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#EBD2FB",
linewidth = 0.1, alpha = .7) +
# capa con puntos
geom_sf(data = cuadrado,
fill = NA,
linewidth = 0.8,
linejoin = "mitre", #linejoin = "round",
color = "#402E5A") +
coord_sf(xlim = c(-72, -56),
ylim = c(-40, -30))
Paso a paso, el proceso de crear el punto, agrandarlo, y formarlo en un cuadrado se vería así:
Ver código del proceso y del gráfico
punto_grande <- punto |>
st_buffer(dist = 100000, max_cells = 10000)
cuadrado <- punto_grande |>
st_bbox(crs = st_crs(mapa)) |>
st_as_sfc() |>
st_as_sf(crs = st_crs(mapa))
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#EBD2FB",
linewidth = 0.1) +
# capas
geom_sf(data = punto,
color = "#402E5A", size = 3) +
geom_sf(data = punto_grande,
fill = NA, color = "#402E5A", lwd = 0.7) +
geom_sf(data = cuadrado,
fill = NA, color = "#402E5A", lwd = 0.7) +
# acercar mapa
coord_sf(xlim = c(-61, -55),
ylim = c(-40, -35.7))
Crear un rectángulo a partir de puntos
Si tenemos varios puntos y necesitamos crear un rectángulo que los contenga a todos, podemos repetir lo anterior pero partiendo de varios puntos a la vez.
# tabla con coordenadas
coordenadas <- tribble(~nombre, ~lon, ~lat, ~n,
"A", -69, -38, 4,
"B", -65, -37, 6,
"C", -61, -36, 9)
# convertir coordenadas a puntos
puntos <- coordenadas |>
# convertir tabla a sf
st_as_sf(coords = c("lon", "lat"),
crs = st_crs(mapa))
# convertir puntos a rectándulo
rectangulo <- puntos |>
st_buffer(dist = 80000) |> # ampliar
st_bbox() |>
st_as_sfc(crs = st_crs(mapa))
Ver código del gráfico
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#EBD2FB",
linewidth = 0.2, alpha = .7) +
# capa con puntos
geom_sf(data = puntos,
alpha = .5) +
geom_sf(data = rectangulo,
fill = NA, color = "#402E5A", lwd = 0.7)
Crear un polígono a partir de coordenadas
Teniendo una tabla con un conjunto de coordenadas, podemos unirlas para formar un polígono. Es decir, unir los puntos para conformar una figura geométrica cerrada. Para ello, usamos st_combine() para combinar las coordenadas en un solo elemento, y luego st_cast() para convertir esos puntos combinados en un polígono.
coordenadas <- tribble(~nombre, ~lon, ~lat,
"A", -68, -36,
"B", -64, -31,
"C", -60, -36)
# convertir tabla a sf
puntos <- coordenadas |>
st_as_sf(coords = c("lon", "lat"),
crs = st_crs(mapa))
poligono <- puntos |>
# combinar coordenadas en un solo elemento
summarise(geometry = st_combine(geometry)) |>
# convertir puntos a polígono
st_cast("POLYGON")
Ver código del gráfico
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#E0C7F0",
linewidth = 0.2, alpha = 0.7) +
# capa con puntos
geom_sf(data = puntos,
alpha = .6) +
# capa con polígono
geom_sf(data = poligono,
fill = "#402E5A", color = "#402E5A",
lwd = 0.7, alpha = 0.7)
Crear varios polígonos a partir de coordenadas
Podemos realizar el mismo proceso anterior, pero agrupando los datos con group_by() para crear varios polígonos a la vez, de acuerdo a la variable de agrupación (en este caso, tipo). Entonces, cuando usemos st_combine(), se combinarán las coordenadas de cada grupo por separado, y luego st_cast() convertirá cada grupo de puntos combinados en un polígono distinto.
coordenadas <- tribble(~tipo, ~lon, ~lat,
"Triángulo", -68, -30,
"Triángulo", -64, -25,
"Triángulo", -60, -30,
"Cuadrado", -68, -38,
"Cuadrado", -60, -38,
"Cuadrado", -60, -32,
"Cuadrado", -68, -32)
# convertir tabla a sf
puntos <- coordenadas |>
st_as_sf(coords = c("lon", "lat"),
crs = st_crs(mapa))
poligono <- puntos |>
# combinar coordenadas en elementos únicos agrupados por una variable
group_by(tipo) |>
summarise(geometry = st_combine(geometry)) |>
# convertir puntos a polígono
st_cast("POLYGON")
Ver código del gráfico
ggplot() +
# mapa de fondo
geom_sf(data = mapa,
fill = "#9069C0", color = "#E0C7F0",
linewidth = 0.2, alpha = 0.7) +
# capa con polígonos de color
geom_sf(data = poligono,
aes(fill = tipo, color = tipo),
lwd = 0.6, alpha = .7) +
# capa con puntos
geom_sf(data = puntos,
alpha = .4) +
# escala de colores
labs(fill = "Tipo", color = "Tipo") +
theme(legend.key.spacing.y = unit(1, "mm"))
Recortar un mapa
Para enfocar un mapa en una zona específica y eliminar el resto de los polígonos, usamos la función st_crop(), definiendo los límites del recorte con las coordenadas mínimas y máximas en los ejes x (longitud) e y (latitud).
Primero obtengamos un mapa de Chile desde {rnaturalearth}:
library(rnaturalearth)
chile <- ne_countries(country = "Chile", scale = 10) |>
select(pais = admin,
region = name_es,
geometry)
Ahora lo recortamos con st_crop(). Recomiendo hacerlo terminando el recorte con una visualización del mapa, para ver inmediatamente el resultado y así poder ir ajustando el recorte:
chile_recortado <- chile |>
st_crop(xmin = -78, ymax = -17,
xmax = -65, ymin = -56)
En este caso, hacemos un recorte para obtener el territorio continental de Chile (excluyendo las islas Juan Fernández, Isla de Pascua y Antártica)
Ver código del gráfico
mapa_completo <- chile |>
ggplot() +
geom_sf(fill = "#9069C0", linewidth = 0)
mapa_recortado <- chile_recortado |>
ggplot() +
geom_sf(fill = "#9069C0", linewidth = 0)
# poner los dos mapas lado a lado
library(patchwork)
mapa_completo + mapa_recortado
También podemos hacer recortes que pasen por encima de los polígonos, eliminando la geografía que quede fuera del recorte. En este caso hacemos un recorte más cercano a la zona costera de Temuco y Valdivia:
Mover puntos de un mapa
Cuando ya contamos con tabla con datos geoespaciales en puntos, a veces es necesario mover la posición de los puntos en un mapa, por ejemplo, para evitar que se sobrepongan etiquetas, para ajustar una coordenada incorrecta, o para mejorar la visualización.
Los puntos pueden moverse al modificar las coordenadas de la geometría. En el caso de los puntos se las coordenadas son un vector de dos elementos (longitud y latitud), por lo que podemos sumar o restarle a la columna geometry para modificar la posición de cada punto.
Creemos una tabla con latitudes y longitudes, y convirtámosla a sf con st_as_sf(),
como vimos antes:
puntos <- tribble(~nombre, ~lon, ~lat,
"Hualqui", -8113368, -4434476,
"Coronel", -8136065, -4440419,
"Concepción", -8132714, -4414370,
"Lota", -8139383, -4451456,
"Penco", -8119934, -4402016,
"Talcahuano", -8139277, -4399701) |>
# convertir a tabla sf
st_as_sf(coords = c("lon", "lat"),
crs = 3395)
Así se ven los puntitos por sí solos:
Ahora recortemos el mapa de Chile para enfocarnos en la zona donde están los puntos.
Creamos un buffer alrededor de los puntos para agrandarlos con st_buffer(), y luego
calculamos la caja que los contiene con st_bbox() para usarla como recorte.
caja_puntos <- puntos|>
st_buffer(50000) |> # agrandar puntos
st_bbox() # calcular caja que contiene a los puntos
Ahora que tenemos la caja, la usamos dentro de st_crop() para recortar el mapa, pero ojo, que ambas capas tienen que tener el mismo sistema de referencias de coordenadas (CRS), así que primero transformamos el mapa de Chile con st_transform() para que use el mismo sistema que la capa de puntos.
chile_recorte <- chile |>
# ajustar crs para que coincidan
st_transform(crs = st_crs(puntos)) |>
# recortar con la caja (bounding box)
st_crop(caja_puntos)
Ver código del gráfico
ggplot() +
geom_sf(data = chile_recorte,
fill = "#9069C0", color = "#E0C7F0", alpha = 0.5) +
geom_sf(data = puntos,
color = "#402E5A", size = 3, alpha = 0.7) +
geom_sf_text(data = puntos,
aes(label = paste(" ", nombre)),
color = "#402E5A", size = 3, hjust = 0, angle = -35)
Imaginemos que queremos mover o modificar puntos específicos del mapa. Igual como haríamos con una tabla de datos, usamos mutate() para modificar la columna geometry, que contiene las coordenadas de cada punto, y le aplicamos una función para modificar sus valores condicionalmente, como case_when(). Así podemos modificar los puntos dependiendo de si coinciden con criterios basados en datos, en vez de hacerlo a mano.
Para este ejemplo, modificaremos puntos a partir de su valor en la variable nombre. Simplemente sumamos a las coordenadas de los puntos que queremos mover, recordando que como es un vector de dos elementos, sumamos un vector de dos elementos. Para moverlos horizontalmente (hacia el este), sumamos a la primera posición del vector (longitud, c(7000, 0)) y dejamos la segunda posición (latitud) en cero.
El problema es que, al hacer esto, convertimos las coordenadas en meros números, por lo que pierden atributos geométricos, lo que causa problemas. Para resolverlo, le sacamos también los atributos geométricos a los demás puntos que no se mueven (con st_set_crs(NA)), y después luego le reasignamos el sistema de coordenadas (CRS) original a toda la tabla con st_set_crs().
puntos_movidos <- puntos |>
# modificar puntos condicionalmente
mutate(geometry = case_when(nombre == "Hualqui" ~ geometry + c(7000, 0),
nombre == "Penco" ~ geometry + c(7000, 0),
.default = st_sfc(geometry) |> st_set_crs(NA))
) |>
st_set_crs(st_crs(puntos))
Otra alternativa sería…
Otra alternativa al problema de perder las coordenadas al modificar los puntos es hacer lo contrario: volver a agregar las coordenadas a cada observación que se modifique agregándoles st_set_crs(st_crs(mapa)), y dejando las demás observaciones sin cambios.
puntos |>
mutate(geometry = case_match(nombre,
"Hualqui" ~ st_sfc(geometry + c(7000, 0)) |> st_set_crs(st_crs(puntos)),
"Tomé" ~ st_sfc(geometry + c(7000, 0)) |> st_set_crs(st_crs(puntos)),
.default = geometry)
)
Personalmente encuentro que la primera forma es más legible.
Lo que sumemos o restemos a las coordenadas depende del sistema de coordenadas de cada mapa. En algunos va a haber que sumar números muy pequeños, pero en otros sistemas de coordenadas se usan números muy grandes.
En el gráfico vemos en color más tenue las posiciones originales de los puntos que fueron modificados.
Ver código del gráfico
ggplot() +
geom_sf(data = chile_recorte,
fill = "#9069C0", color = "#E0C7F0", alpha = 0.5) +
geom_sf(data = puntos,
color = "#402E5A", size = 3, alpha = 0.2) +
geom_sf(data = puntos_movidos,
color = "#402E5A", size = 3, alpha = 0.7) +
geom_sf_text(data = puntos_movidos,
aes(label = paste(" ", nombre)),
color = "#402E5A", size = 3, hjust = 0, angle = -35)