How to create a cartogram-heatmap (non-US)

419 views Asked by At

I want to create a map like:

edit: this screenshot is from Claus Wilkes book Fundamentals of Data Visualization

But as I'm living in Switzerland, I haven't found a package where I can use this out of the box. Also I haven't found something for Germany or Austria.

Then I discovered the package geofacet, which covers many countries (even smaller ones like CH) and allows to create a grid like:

After some tweeking arround a while, I managed to get to this point:

There are still some details, which I need to fix, but I'm facing two problems, that I don't know how to solve:

  1. How can I plot rounded squares (like in the initial picture)?
  2. How can I use the state/canton name in the middle of the plot, like a watermark? I my last attempt, I removed the facet label and used an annotation, but couldn't use the state values from the column.

I would appreciate any help. Also if there is anyone out there who has had the same problem in the past and found an easier solution than mine.

MWE

This is the code for the last plot:

library(ggplot2)
library(geofacet)

test = data.frame("state"=c("ZH", "AG", "TI", "BS"), value=c(1,2,3,4))

ggplot(data=test, aes(fill=value)) +
  geom_rect(mapping=aes(xmin=1, xmax=2, ymin=1, ymax=2), color="black", alpha=0.5) +
  annotate("text", x=1.5, y=1.5, label= "state") +
  facet_geo(~state, grid="ch_cantons_grid2") +
  theme_minimal() + 
  theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.y=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        strip.placement = "bottom",
        plot.title = element_text(hjust = 5),
        strip.background = element_blank(),
        strip.text.x = element_blank())
1

There are 1 answers

0
Guillaume On BEST ANSWER

Maybe something like this:

For rounded square, see hrbrmstr/statebins

library(ggplot2)
library(geofacet)
library(dplyr)
test = data.frame(state=c("ZH", "AG", "TI", "BS"), value=c(1,2,3,4))

# devtools::install_github("hrbrmstr/statebins")

grid_geo <- geofacet::ch_cantons_grid2$code

test$state <- factor(test$state, levels = grid_geo)

test <- dplyr::right_join(test, dplyr::tibble(grid_geo), by = c('state' = 'grid_geo'))

ggplot(data=test ) +
    statebins:::geom_rrect(data=test, mapping=aes(xmin=1, xmax=2, ymin=1, ymax=2), 
                           fill = 'white', 
                           color="black", alpha=0.5) +
    statebins:::geom_rrect(data=test %>% 
                               dplyr::filter(!is.na(value)),
                                             mapping=aes(xmin=1, xmax=2, ymin=1, ymax=2, fill =  value), 
              color="black", alpha=0.5) +
    geom_text(data=test, aes(x = 1.5, y = 1.5, label = state)) +
    # annotate("text", x=1.5, y=1.5, label= state) +
    facet_geo(~state, grid="ch_cantons_grid2") +
    theme_minimal() + 
    theme(axis.title.x=element_blank(),
          axis.text.x=element_blank(),
          axis.ticks.x=element_blank(),
          axis.title.y=element_blank(),
          axis.text.y=element_blank(),
          axis.ticks.y=element_blank(),
          strip.placement = "bottom",
          plot.title = element_text(hjust = 5),
          strip.background = element_blank(),
          strip.text.x = element_blank(), 
          line = element_blank())


enter image description here

Here is another code to mimick the visual that you show.

ggplot(data=test) +
    statebins:::geom_rrect(data=test, mapping=aes(xmin=1, xmax=2, ymin=1, ymax=2), 
                           fill = '#d0e1e1', 
                           color=NA, alpha=0.7) +
    statebins:::geom_rrect(data=test %>% 
                               dplyr::filter(!is.na(value)),
                                             mapping=aes(xmin=1, xmax=2, ymin=1, ymax=2, fill =  value), 
              color=NA, alpha=1) +
    geom_text(data=test, aes(x = 1.5, y = 1.5, label = state)) +
    # annotate("text", x=1.5, y=1.5, label= state) +
    facet_geo(~state, grid="ch_cantons_grid2") +
    scale_fill_gradient(low = "#dccbd7", high = '#564364', name = "Label value") +
    theme_minimal() + 
    guides(fill = guide_legend(title.position = "top")) +
    theme(legend.position = c(0.2, 0.95), 
          legend.direction="horizontal") +
    theme(axis.title.x=element_blank(),
          axis.text.x=element_blank(),
          axis.ticks.x=element_blank(),
          axis.title.y=element_blank(),
          axis.text.y=element_blank(),
          axis.ticks.y=element_blank(),
          strip.placement = "bottom",
          plot.title = element_text(hjust = 5),
          strip.background = element_blank(),
          strip.text.x = element_blank(), 
          line = element_blank())

enter image description here

You can change guides(fill = guide_legend(title.position = "top")) by guides(fill = guide_colorbar(title.position = "top")) to have continuous color scale.

enter image description here