ccamara ccamara - 24 days ago 4
R Question

Adding an overlay in a facetted map using ggplot

An image is worth a thousand words:

enter image description here

As can be seen in the image, I have created a facetted maps with ggplot, but each facet is lacking the countries wich do not have any value for that particular variable (although that does not explain grey countries like the ones in var3 facet). My guess is that adding a new geometry layer below would fix this, but unfortunately I do not have any clue to fix this.

Desired output:

What I would like to achieve is that all countries were displayed in all facets, and in case they do not have a value for that particular value should be outputted in another colour (grey, for example). By doing that, the world map would always be complete instead of presenting holes which makes it really weird to read.

I would like to achieve something like this, but for every facet (and obviously values and colors would have to change):

enter image description here

That's the code I've used so far:

library(rgdal)
library(dplyr)
library(broom)
library(ggplot2)

world = readOGR(dsn = "https://gist.githubusercontent.com/ccamara/fc26d8bb7e777488b446fbaad1e6ea63/raw/a6f69b6c3b4a75b02858e966b9d36c85982cbd32/countries.geojson")


# Load dataframe.
df = read.csv("https://gist.githubusercontent.com/ccamara/fc26d8bb7e777488b446fbaad1e6ea63/raw/519c6199c9fc24df87bb6ca0bfcd0413db6e3617/sample-dataframe-grouped.csv")

world.t = tidy(world, region = "name")

# join with the original file's data
world.t = left_join(world.t, world@data, by = c("id" = "name"))

# join with df
world.t = left_join(world.t, df, by = c("iso_a2" = "country_code"))

ggplot(data = world.t, aes(long, lat, fill = value, group = group)) +
facet_wrap(~variable) +
scale_fill_gradient(low = "yellow", high = "red") +
#scale_fill_brewer(type = "seq", palette = "Reds")+
geom_polygon() +
geom_path(colour = "black", lwd = 0.05) +
coord_equal() +
ggtitle("Countries without values are not displayed") +
labs(fill = "amount") +
theme(axis.text = element_blank(),
axis.title = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank())


Also, after reading this other question, I made a slight adaptation to it, but the new layer is displayed over the previous ones instead of below them.

map.1 = ggplot(data = world.t,
aes(long, lat, fill = value, group = group)) +
facet_wrap(~variable) +
scale_fill_gradient(low = "yellow", high = "red") +
geom_polygon() +
geom_path(colour = "black", lwd = 0.05) +
coord_equal() +
ggtitle("New layer hides everything else") +
labs(fill = "amount") +
theme(axis.text = element_blank(),
axis.title = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank())


map.1 + geom_polygon(data=world.t,
aes(x=long, y=lat, group=group), lwd = 0.01, fill = "blue", inherit.aes = F)


enter image description here

Answer Source

I modified your code to capture the world map at the beginning:

base_world = tidy(world, region = "name") 

world.t = base_world

# join with the original file's data
world.t = left_join(world.t, world@data, by = c("id" = "name"))

# join with df
world.t = left_join(world.t, df, by = c("iso_a2" = "country_code"))

world.t <- filter(world.t, !is.na(variable))

ggplot(data = world.t[!is.na(world.t$value),],
               aes(long, lat, fill = value, group = group)) +
  facet_wrap(~variable) +
  scale_fill_gradient(low = "yellow", high = "red") +
  geom_polygon(data=base_world[base_world$order,],
               aes(x=long, y=lat, group = group), 
               lwd = 0.01, fill = "grey", inherit.aes = F) + #Put original map in
  geom_polygon() + #Draw data on top
  geom_path(colour = "black", lwd = 0.05) +
  coord_equal() +
  ggtitle("Now it looks a little better") +
  labs(fill = "amount") +
  theme(axis.text = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank(),
        panel.grid = element_blank())

enter image description here