user63230
user63230

Reputation: 4636

correct positioning of ggplot insets with ggpmisc in facet

How can I flexibly position an inset using ggpmisc without changing the width and height of the inset itself?

library(tidyverse)
library(sf)  
library(ggpmisc)

#data
nc <- st_read(system.file("gpkg/nc.gpkg", package = "sf"), quiet = TRUE) %>%
  st_transform(st_crs(4326)) %>%
  st_cast('POLYGON')

#create timeseries data
nc_2 <- rbind(nc %>% mutate(timepoint = 1), nc %>% mutate(timepoint = 2))
#create base plot
nc_2_base <- ggplot(data = nc_2) + 
  geom_sf(aes(fill = BIR74)) + 
  coord_sf(xlim = c(-80, -76), 
           ylim = c(32, 37), expand = FALSE)
#facet plot
nc_2_main <- nc_2_base + facet_wrap(~timepoint, dir = "h", ncol = 2) 

#extract number of timepoints
nmax_rep_nc <- length(unique(nc_2$timepoint))

#create insets
insets_nc <- lapply(seq_len(nmax_rep_nc), function(i) {
  nc_2_base + ggforce::facet_wrap_paginate(~ timepoint, nrow = 1, ncol = 1, page = i) +
    coord_sf(xlim = c(-79.5, -78.5), ylim = c(34.5, 35.5)) +
    theme(strip.background = element_blank(),
          strip.text = element_blank(),
          axis.title = element_blank(),
          plot.background = element_blank(),
          legend.position = "none")
})

To position the insets you need to create a tibble with x, y indicating the position you want. Here, I want them in the bottom left corner so specify x = 0.0 and y = 0 (x, y can be 0 - 1 from the vignette here) and I want the size of the insets to be 50% of the main plot (vp.width = 0.5, vp.height = 0.5):

insets_nc_tibble <- tibble(x = rep(0.0, nmax_rep_nc),
                           y = rep(0.0, nmax_rep_nc),
                           plot = insets_nc,
                           timepoint = unique(nc_2$timepoint))
#add inset to plot:
nc_2_main +
  geom_rect(xmin = -79.5, xmax = -78.5, ymin = 34.5, ymax = 35.5, 
            fill = NA, colour = "red", size = 1.5) +
  geom_plot_npc(data = insets_nc_tibble, 
                aes(npcx = x, npcy = y, label = plot,
                    vp.width = 0.5, vp.height = 0.5))

which produces this plot:

enter image description here

But the inset isn't correctly in the bottom left corner (0, 0) as I wanted. How can I keep the inset this size but move it so it is directly in the corner?

If I reduce the size of the inset it seems to help but this is completely trial and error and I don't want to reduce the size of the inset.

#reduce size
nc_2_main +
  geom_rect(xmin = -79.5, xmax = -78.5, ymin = 34.5, ymax = 35.5, 
            fill = NA, colour = "red", size = 1.5) +
  geom_plot_npc(data = insets_nc_tibble, 
                aes(npcx = x, npcy = y, label = plot,
                    vp.width = 0.5, vp.height = 0.25))

This produces this plot which is better positioning but not the correct size I want:

enter image description here

Note, you can also specify corner by string but this doesn't help:

#insets_nc_tibble <- tibble(x = rep("left", nmax_rep_nc),
#                           y = rep("bottom", nmax_rep_nc),
#                           plot = insets_nc,
#                           timepoint = unique(nc_2$timepoint))

This question is a follow up to my previous answer and others here.

I don't understand how changing the size, changes the position. I thought specifying x, y = 0, 0 means the bottom left corner of the inset should be set to 0, 0 but doesn't seem the case here?

Any ideas?

thanks

Upvotes: 1

Views: 406

Answers (1)

Pedro J. Aphalo
Pedro J. Aphalo

Reputation: 6508

This looks like a bug. I will investigate why there is a shift of 0.5 degrees in the x axis.

Here is a temporary workaround using the non-noc version of the geom and shifting the x coordinates by -0.5 degrees:

insets_nc_tibble1 <- tibble(x = rep(-80, nmax_rep_nc),
                            y = rep(31.5, nmax_rep_nc),
                            plot = insets_nc,
                            timepoint = unique(nc_2$timepoint))

#add inset to plot:
nc_2_main +
  geom_rect(xmin = -79.5, xmax = -78.5, ymin = 34.5, ymax = 35.5, 
            fill = NA, colour = "red", size = 1.5) +
  geom_plot(data = insets_nc_tibble1, 
            aes(x = x, y = y, label = plot),
            vp.width = 0.5, vp.height = 0.5)

enter image description here

The reason is that the grid viewport for the rendered plot is larger than the plot itself. Whether this a feature or a bug in 'ggplot2' is difficult to say as lat and lot would be otherwise distorted. Can be seen by printing the ggplot and then running grid::showViewport(). This seems to be the result of using fixed coordinates so that the inset plot cannot stretch to fill the available space in the viewport.

Upvotes: 1

Related Questions