ggplot2 和 sf:geom_sf_text 在 coord_sf 设定的范围内

ggplot2 and sf: geom_sf_text within limits set by coord_sf

我正在使用 sfggplot2 将 shapefile 读取为简单特征并绘制各种地图。我一直在研究 maps chapter in the ggplot2 book 但无法真正找到以下问题的答案:

使用 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)

我找到了一种解决方法来放大地图的各个部分,并且仍然能够通过计算特征的质心来标记图中存在的特征,将坐标提取为单独的列,select编辑我希望在最终地图中显示的元素,并使用 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 和 select 中提取坐标,最终显示的标签地图。

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

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

我认为您面临的问题是由于您在 presentation 级别应用裁剪/未裁剪 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))