Harish
Harish

Reputation: 295

Plot a numerical values in United states map based on Abbreviated state names

I have a data as below that has all the states. Providing a sample here,

state_name value_x
AL 250
AK 900
.
.

MT 1000
NJ 10000
.
WY 500

Now I need to plot these numbers(value_x) in US map according to state abbreviations.

I tried reading about this package fiftystater online. But i am not getting anywhere in plotting this.

I read this stackoverflow post too. But i don't know how to apply to to my specific dataset.

How to map all the states of US using R with the number of crimes occurred in each state?

Please help! I want to visualize my graph something like this. I took this image from the stackoverflow post.

enter image description here

Upvotes: 2

Views: 3580

Answers (1)

Calum You
Calum You

Reputation: 15072

Your question is almost identical to the linked question except for the fact that your data does not have the lowercase state names already present.

library(tidyverse)
library(fiftystater)
library(viridis)
#> Loading required package: viridisLite

Construct a sample dataset using built in datasets. You do not need to do this part, just call your values to plot tbl

tbl <- state.x77 %>%
  as_tibble(rownames = "state") %>%
  bind_cols(state_name = state.abb) %>%
  rename(value_x = Income) %>%
  select(state_name, value_x)

Create a table that relates state names to state abbreviations:

state_abbs <- tibble(state = str_to_lower(state.name), abb = state.abb)

Use left_join to join the full state names to the data table that only has abbreviations:

tbl_m <- left_join(tbl, state_abbs, by = c("state_name" = "abb")) %>%
  rename(id = state)

And then basically copy the example from fiftystater or from the answer to the linked question. Here the first key part is geom_map, which needs you to use option map = fifty_states where fifty_states is the data table from fiftystater, and also to supply aes(map_id = id) so that it knows which group of points corresponds to which values in the data. The second key part is geom_text, which adds the text you want at coordinates you specify. Here, we create a dataframe that makes the coordinates the mean of the lat or long for each state from fifty_states, and then join it to the data in tbl_m. The rest is just formatting!

ggplot(tbl_m) +
  geom_map(map = fifty_states, aes(map_id = id, fill = value_x)) + 
  expand_limits(x = fifty_states$long, y = fifty_states$lat) +
  coord_map() +
  geom_text(
    data = fifty_states %>%
      group_by(id) %>%
      summarise(lat = mean(c(max(lat), min(lat))),
                long = mean(c(max(long), min(long)))) %>%
      mutate(state = id) %>%
      left_join(tbl_m, by = c("state" = "id")),
    aes(x = long, y = lat, label = value_x )
    ) +
  scale_fill_viridis() +
  scale_x_continuous(breaks = NULL) +
  scale_y_continuous(breaks = NULL) +
  labs(x = "", y = "") + theme(legend.position = "bottom", 
                               panel.background = element_blank())
#> Warning: Removed 1 rows containing missing values (geom_text).

Created on 2018-02-16 by the reprex package (v0.2.0).

Upvotes: 4

Related Questions