首页 > 解决方案 > 在 ggplot 图中裁剪未使用的边距

问题描述

我创建了一个要保存为 svg 的 ggplot 世界地图。两者都工作正常。但是,我想更改/指定要保存的绘图区域。

我的代码如下所示:

raw_plot = ggplot(data = world_for_plot,
                  aes(x = long,
                      y = lat,
                      group = group,
                      fill = "black")) +
  geom_polygon(aes(fill = results)) +
  coord_equal(1.3, expand=F) +
  scale_fill_continuous(na.value = '#F6F6F6', guide=F)

ggsave(file = "FOLDER\\LATAM.svg",
       plot = raw_plot)

这给了我以下情节:

在此处输入图像描述

但是,我希望有一个文件/绘图在顶部和底部没有所有不必要的空白:

在此处输入图像描述

有任何想法吗?我已经发现该coord_equal命令会产生一些问题。没有它,情节将填满整个情节区域。但是,我需要这个coord_equal命令,否则世界地图会显得有些拉长。

标签: rggplot2crop

解决方案


我最近遇到了同样的问题,所以这是我为有同样问题的人提供的解决方案。

tmaptools具有get_asp_ratio计算空间对象纵横比的功能。我们可以使用该比率来删除任何地图的外边距。

library(ggplot2)

world <- rnaturalearth::ne_countries(returnclass = "sf") # to get the world map

ggplot() +
  geom_sf(data = world) +
  coord_sf(expand = FALSE) +
  theme_void()

asp <- tmaptools::get_asp_ratio(world) # returns 2.070007

height <- 5
ggsave("world.svg", width = height * asp, height = height)

或者,如果我们不想依赖tmaptools,我们可以使用包装器来创建自己的函数ggsave。这本质上是基于tmaptools::get_asp_ratio函数的。

deg_to_rad <- function(x) {
  (mean(x) * pi) / 180
}

get_aspect_ratio <- function(geometry) {
  if (!inherits(geometry, c("Spatial", "Raster", "sf", "sfc"))) {
    stop('"geometry" must be of class "Spatial", "Raster", "sf" or "sfc".')
  }
  bbox <- sf::st_bbox(geometry)
  xlim <- bbox[c(1, 3)]
  ylim <- bbox[c(2, 4)]
  xdeg <- diff(xlim)
  ydeg <- diff(ylim)
  if (xdeg == 0 || ydeg == 0) {
    asp <- 1
  } else {
    is_lon_lat <- sf::st_is_longlat(geometry)
    asp <- unname((xdeg / ydeg) * ifelse(is_lon_lat, cos(deg_to_rad(ylim)), 1))
  }
  asp
}

save_ggmap <- function(filename, plot = last_plot(), width = NA, height = NA, ...) {
  geometry <- ggplot_build(plot)$data[[1]]$geometry
  asp <- get_aspect_ratio(geometry)
  if (is.na(width) && !is.na(height)) {
    width <- height * asp
  } else if (is.na(height) && !is.na(width)) {
    height <- width / asp
  }
  ggsave(filename, plot, width = width, height = height, ...)
}

我们可以像使用这个函数一样ggsave。我们只需要指定widthorheight和函数将自动以正确的纵横比保存地图。

ggplot() +
  geom_sf(data = world) +
  coord_sf(expand = FALSE) +
  theme_void()

save_ggmap("world.svg", width = 8)

要删除内边距,我们可以使用theme(plot.margin = margin(0, 0, 0, 0)).


推荐阅读