Добавление надписей на карты с помощью линий

Я хотел бы построить карту с помощью geom_sf() и добавить метки, как показано на следующей карте, созданной вручную (но нам не нужны цвета или легенда, это просто карта, которая у нас была под рукой).

Новая карта:

Данные карты можно скачать здесь. Карта состоит из трех столбцов: «Kommunenummer» (номер муниципалитета), «Kommunenavn» (название муниципалитета), «геометрия». На карте выше указаны два объекта: муниципалитеты Волда (юг) и Тромсё (север).

Я думаю, нам нужно будет определить положение центроида этих муниципалитетов, а затем использовать что-то вроде geom_text_repel(), чтобы указать на них, но у меня это не получилось. Есть ли у кого-нибудь советы?

Минимальный рабочий пример:

mapdata <- st_read("~/Downloads/Basisdata_0000_Norge_25833_NorskeFylkerKommunerIllustrasjonsdata2021_GeoJSON/kommuner2021.json")

ggplot(mapdata) +
  geom_sf() +
  theme_minimal() +
  theme(
    panel.grid.major = element_blank(),   # Removes major grid lines
    panel.grid.minor = element_blank(),   # Removes minor grid lines
    axis.text.x = element_blank(),        # Removes x-axis labels (Longitude)
    axis.text.y = element_blank(),        # Removes y-axis labels (Latitude)
    axis.title.x = element_blank(),       # Removes x-axis title
    axis.title.y = element_blank()        # Removes y-axis title
  )

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы не работаете с сотнями лейблов, ggrepel зачастую не самый эффективный подход. Вы можете потратить слишком много времени на то, чтобы метки отображались правильно, а исправление проблем может создать проблемы в другом месте.

Обычно мне проще использовать пакет sf и создавать геометрию этикеток вручную. Чтобы правильно расположить метки, может потребоваться некоторое время методом проб и ошибок, но, имея всего несколько меток, почти всегда легче получить желаемый результат, чем при использовании ggrepel. Кроме того, я не уверен, что ggrepel принимает функции, например. ggtext, чтобы можно было использовать шрифты разного размера для меток графиков.

В этом ревыражении используется одинаковое смещение -/+0,5 десятичных градусов для обеих меток. Ничто не мешает вам установить разные смещения для каждой метки. Поскольку мой норвежский язык немного «заржавел», я не смог загрузить связанные с вами данные, поэтому применил этот рабочий процесс к встроенному набору данных ЧПУ. Ваши смещения могут отличаться от CRS ваших фактических данных.

Я использовал st_point_on_surface() вместо st_centroid(), чтобы точка не отображалась за пределами многоугольника (что может произойти с некоторыми многоугольниками неправильной формы). Обратите внимание: st_point_on_surface() вряд ли отобразит истинное местоположение центроида в тех случаях, когда в противном случае st_centroid() нарисовал бы его внутри многоугольника. Если это нежелательно, замените st_point_on_surface() на st_centroid().

Загрузите пакеты и пример данных карты:

library(sf)
library(dplyr)
library(ggplot2)

# Example data
mapdata <- st_read(system.file("shape/nc.shp", package = "sf"))

Создайте геометрию этикетки:

# Create 'centroids' of municipalities (you can safely ignore the warning)
sf_centroids <- mapdata %>%
  filter(NAME %in% c("Watauga", "Swain")) %>% # proxies for your municipalities
  st_point_on_surface()

# Create points for label locations
sf_labels <- sf_centroids %>%
  mutate(lon = st_coordinates(.)[,1] - 0.5,
         lat = st_coordinates(.)[,2] + 0.5) %>%
  st_drop_geometry() %>%
  st_as_sf(coords = c("lon", "lat")) %>%
  st_set_crs(st_crs(sf_centroids))

# Create lines between label locations and centroids
sf_lines <- rbind(sf_labels[,"NAME"], 
                  sf_centroids[,"NAME"]) %>%
  group_by(NAME) %>%
  summarise(geometry = st_union(geometry)) %>%
  st_cast("LINESTRING")

Создайте списки меток и постройте график:

# Create labels
labels1 <- c("Exp's 2-3 - Northern Norway:", "Exp 1 - Sunnmøre:")
labels2 <- c("Bokmål vs. Northern Norwegian Dialect", "Bokmål")

# Plot labels using geo_sf_text
ggplot() + 
  geom_sf(data = mapdata) +
  geom_sf(data = sf_lines, linewidth = 0.15) +
  geom_sf(data = sf_labels, shape = 21, fill = "white", size = 0.75) +
  geom_sf(data = sf_centroids, size = 0.75) +
  geom_sf_text(data = sf_labels,
               aes(label = labels1),
               size = 2,
               vjust = -2,
               fun.geometry = st_centroid,
               colour = "black") +
  geom_sf_text(data = sf_labels,
               aes(label = labels2),
               size = 1.5,
               vjust = -1,
               fun.geometry = st_centroid,
               colour = "black") +
  coord_sf(clip = "off") +
  theme_void()

Отлично! Спасибо! Гораздо более элегантное решение, чем то, что мне удалось с помощью ggrepel.

user9974638 26.04.2024 07:33

Другие вопросы по теме