r - 在 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
命令,否则世界地图会显得有些拉长。
解决方案
我最近遇到了同样的问题,所以这是我为有同样问题的人提供的解决方案。
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
。我们只需要指定width
orheight
和函数将自动以正确的纵横比保存地图。
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))
.
推荐阅读
- node.js - 'clinic' 不是内部或外部命令、可运行程序或批处理文件
- python - 如何根据另一个值的中位数替换缺失值?
- openstack - 实例无法从 OPENSTACK 中的 DHCP 服务器获取任何 IP
- android - `remember` 是否仅适用于`MutableState` 变量?
- android - 在列表视图中搜索最后一个或中间活动后出现问题
- kotlin - 禁止用户不关闭 BottomSheetScaffold
- angular - 编译依赖于其他自定义角度库的自定义角度库会产生 TS7016 错误
- android - 无法在 Android 项目中设置 ActionBar 文本颜色
- python - 根据条件创建列
- string - 一个 Spark Scala 字符串匹配 UDF