Home > Software engineering >  Both geom_vline and geom_hline fails when faceting spatial map on ggplot2
Both geom_vline and geom_hline fails when faceting spatial map on ggplot2

Time:02-25

I am really careful before posting this this question, in order to avoid any duplication. So I intended to create a faceting map based on quarter, equipped with both major and minor grid, whereas the latitude and longitude labels only on major grid. Here is the MWE:

library(sf)
library(rnaturalearth)

sf::sf_use_s2(FALSE)

dummy <- data.frame(
  Lat1 = seq(-14.5, 4.5, by = 1),
  Lon1 = seq(105.5, 124.5, by = 1),
  quarter = rep(1:4, 10)
)

worldmap <- ne_countries(scale = 'medium', type = 'map_units', returnclass = 'sf')
wpp <- st_crop(worldmap, ymin = -15, ymax = -5, xmin = 105, xmax = 125)

minor.x <- seq(105, 125, by = 1)
minor.y <- seq(-15, -5, by = 1)


ggplot()  
  geom_sf(data = wpp, color = "gray", fill = "gray")  
  coord_sf(xlim=c(min(data.pie$Lon1-0.5),max(data.pie$Lon1) 0.5),
           ylim=c(min(data.pie$Lat1)-0.5,max(data.pie$Lat1) 0.5),
           expand = FALSE)  
  geom_hline(aes(yintercept = minor.y), color = "gray", linetype = "solid", size = 0.1)  
  geom_vline(aes(xintercept = minor.x), color = "gray", linetype = "solid", size = 0.1)  
  geom_point(data = dummy, aes(x = Lon1, y = Lat1), color= "black")  
  
  xlab("Longitude")   ylab("Latitude")  
  
  scale_x_continuous(breaks = seq(105,125,2), minor_breaks = seq(106, 124, 2))  
  scale_y_continuous(breaks = seq(-15,-5,2), minor_breaks = seq(-14, -4, 2))  
  
  facet_wrap(~quarter)  
  
  theme_minimal()  
  theme(
    # panel.grid.minor = element_line(color = "blue", size = 0.1),
    panel.grid.major = element_blank(),
    panel.background = element_rect(colour = "black", size=0.5),
    legend.position = "right",
    legend.title.align = 0.5,
    legend.text.align = 1) 

Without faceting I could produce the desired outputthe desired output

However, when I use facet_wrap(~quarter) there was an error: Error in FUN(X[[i]], ...) : subscript out of bounds

I managed to produce a faceting map if I turned off the geom_vline and geom_hline but at the same time, I will lose the control over minor grid (only major was shown. Is there any workaround on this? PS. I am using the latest R and ggplot() version.

CodePudding user response:

The issue is that you wrapped x/yintercept inside aes(). Not 100% sure about the reason, but my guess is that when facetting by quarter ggplot2 is looking for a column called quarter in the data passed to geom_hline/vline too. However, as there is neither a global nor a local data you get an error.

As a more minimal reprex of this issue:

library(ggplot2)

ggplot()  
  geom_point(data = mtcars, aes(hp, mpg))  
  geom_point(aes(x = 1, y = 1), color = "red")  
  facet_wrap(~cyl)
#> Error in FUN(X[[i]], ...): subscript out of bounds

To fix your issue set the x/yintercept as arguments instead of as aesthetics.

library(sf)
library(rnaturalearth)
library(ggplot2)

ggplot()  
  geom_sf(data = wpp, color = "gray", fill = "gray")  
  coord_sf(
    xlim = range(dummy$Lon1)   c(-0.5, 0.5),
    ylim = range(dummy$Lat1)   c(-0.5, 0.5),
    expand = FALSE
  )  
  geom_hline(yintercept = minor.y, color = "gray", linetype = "solid", size = 0.1)  
  geom_vline(xintercept = minor.x, color = "gray", linetype = "solid", size = 0.1)  
  geom_point(data = dummy, aes(x = Lon1, y = Lat1), color = "black")  
  xlab("Longitude")  
  ylab("Latitude")  
  scale_x_continuous(breaks = seq(105, 125, 2), minor_breaks = seq(106, 124, 2))  
  scale_y_continuous(breaks = seq(-15, -5, 2), minor_breaks = seq(-14, -4, 2))  
  facet_wrap(~quarter)  
  theme_minimal()  
  theme(
    # panel.grid.minor = element_line(color = "blue", size = 0.1),
    panel.grid.major = element_blank(),
    panel.background = element_rect(colour = "black", size = 0.5),
    legend.position = "right",
    legend.title.align = 0.5,
    legend.text.align = 1
  )

  • Related