Reputation: 11016
I have created a ggplot worldmap that I want to save as svg. Both work fine. However, I want to change/specify the area of the plot that gets saved.
My code looks as follows:
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)
This gives me the following plot:
However, I want to have a file/plot that doesn't have all the unnecessary white space on top and bottom:
Any ideas? I already figured out that the coord_equal
command creates some problems. Without it, the plot fills out the whole plot area. However, I need the coord_equal
command, otherwise the world map would look stretched.
Upvotes: 3
Views: 2337
Reputation: 999
I recently faced the same problem so here're my solutions for people with the same issue.
tmaptools
has a function get_asp_ratio
to compute the aspect ratio of spatial objects. We can use that ratio to remove the outer margin of any map.
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)
Alternatively, if we don't want to depend on tmaptools
, we can make our own functions with a wrapper around ggsave
. This is essentially based on the tmaptools::get_asp_ratio
function.
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, ...)
}
We can use the function the same way as ggsave
. We only have to specify either the width
or height
and the function will save the map with the right aspect ratio automatically.
ggplot() +
geom_sf(data = world) +
coord_sf(expand = FALSE) +
theme_void()
save_ggmap("world.svg", width = 8)
To remove the inner margin, we can use theme(plot.margin = margin(0, 0, 0, 0))
.
Upvotes: 1
Reputation: 125
This might work if you adjust the lengths:
raw_plot + theme(plot.margin = margin(-2, 0, -2, 0, "cm"))
The order of the margins here is top, right, bottom, left.
Upvotes: 1