Reputation: 295
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.
Upvotes: 2
Views: 3580
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