首页 > 解决方案 > ggplot2 和 sf:geom_sf_text 在 coord_sf 设置的范围内

问题描述

我正在使用sf并将ggplot2shapefile 读取为简单的特征并绘制各种地图。我一直在研究 ggplot2 书中的地图章节,但无法真正找到以下问题的答案:

geom_sf使用和标记其特征绘制地图geom_sf_text是一项非常简单的任务。

library(ggplot2)
library(sf)
library(ozmaps)

oz_states <- ozmaps::ozmap_states

ggplot() +
  geom_sf(data = oz_states) +
  geom_sf_text(data = oz_states, aes(label = NAME))

在此处输入图像描述

一旦我们放大了前一张地图的一部分,并不是图中所有特征的标签都是可见的。

xlim <- c(120.0, 140.0)
ylim <- c(-40, -24)

ggplot() +
  geom_sf(data = oz_states) +
  geom_sf_text(data = oz_states, aes(label = NAME)) +
  coord_sf(xlim = xlim, ylim = ylim)

在此处输入图像描述

我找到了一种解决方法来放大地图的各个部分,并且仍然能够通过计算特征的质心、将坐标提取为单独的列、选择我想要显示的元素来标记图中存在的特征最终的地图,并ggrepel用于标记它们。

library(dplyr)
library(ggrepel)

oz_states_labels <- oz_states %>% st_centroid()

oz_states_labels <- do.call(rbind, st_geometry(oz_states_labels)) %>%
  as_tibble() %>%
  rename(x = V1) %>% 
  rename(y = V2) %>% 
  cbind(oz_states_labels) %>%
  slice(4,5,7,3)

ggplot() +
  geom_sf(data = oz_states) +
  geom_text_repel(data = oz_states_labels, aes(label = NAME, x = x, y = y)) +
  coord_sf(xlim = xlim, ylim = ylim)

在此处输入图像描述

自然,如果可能的话,我想避免首先必须计算质心,从结果中提取坐标sf并选择要在最终地图中显示的标签的解决方法。

因此我的问题是:是否有一种更快的方法来标记图中所有可见的元素,例如通过在geom_sf_text或中指定它coord_sf

提前感谢您的提示和答案!

标签: rggplot2dplyrsfggrepel

解决方案


我相信您面临的问题是由于您在演示级别应用裁剪/未裁剪 ggplot 对象的实际数据引起的。

我建议在数据级别应用作物,例如通过sf::st_crop(). 在此示例中,我使用您的 xlim 和 ylim 对象的值来创建一个边界框(crop_factor没有充分理由调用) ,通过创建一个名为& 的新对象继续您的原始工作流程来限制oz_states数据级别的范围。oz_cropped

所有的质心和标签,以及现在表现得更好的东西。

library(ggplot2)
library(sf)
library(ozmaps)

oz_states <- ozmaps::ozmap_states


crop_factor <- st_bbox(c(xmin = 120, 
                         xmax = 140, 
                         ymax = -24, 
                         ymin = -40),
                       crs = st_crs(oz_states))

oz_cropped <- st_crop(oz_states, crop_factor)

ggplot() +
  geom_sf(data =oz_cropped) +
  geom_sf_text(data = oz_cropped, aes(label = NAME))

在此处输入图像描述


推荐阅读