Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

r

ggplot2

I am still learning about R and I want to map the States of US with the labels of number of crimes occurred in each state. I want to create the below image.

I used the below code which was available online but I could not label the No of crimes.

    library(ggplot2)
    library(fiftystater)

    data("fifty_states") 
    crimes <- data.frame(state = tolower(rownames(USArrests)), USArrests)
    p <- ggplot(crimes, aes(map_id = state)) + 
      # map points to the fifty_states shape data
      geom_map(aes(fill = Assault), map = fifty_states) + 
      expand_limits(x = fifty_states$long, y = fifty_states$lat) +
      coord_map() +


scale_x_continuous(breaks = NULL) + scale_y_continuous(breaks = NULL) +
  labs(x = "", y = "") + theme(legend.position = "bottom", 
        panel.background = element_blank())

Please can someone help me ?

like image 813
2 revsuser1106925 Avatar asked Oct 21 '17 03:10

2 revsuser1106925


1 Answers

To add text to a plot (map in this case) one needs the text label and the coordinates of the text. Here is an approach with your data:

library(ggplot2)
library(fiftystater)
library(tidyverse)

data("fifty_states") 

ggplot(data= crimes, aes(map_id = state)) + 
  geom_map(aes(fill = Assault),  color= "black", map = fifty_states) + 
  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(crimes, by = "state"), aes(x = long, y = lat, label = Assault ))+
  scale_x_continuous(breaks = NULL) + scale_y_continuous(breaks = NULL) +
  labs(x = "", y = "") + theme(legend.position = "bottom", 
                               panel.background = element_blank())

enter image description here

Here I used the Assault number as label and mean of the maximum and minimum of lat and long coordinates of each state as text coordinates. The coordinates could be better for some states, one can add them by hand or use chosen city coordinates.

EDIT: with the updated question:

First select the year and type of crime and aggregate the data

homicide %>%
  filter(Year  == 1980 & Crime.Type == "Murder or Manslaughter") %>%
  group_by(State) %>%
  summarise(n = n()) %>%
  mutate(state = tolower(State)) -> homicide_1980

and then plot:

ggplot(data = homicide_1980, aes(map_id = state)) + 
  geom_map(aes(fill = n),  color= "black", map = fifty_states) + 
  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(homicide_1980, by = "state"), aes(x = long, y = lat, label = n))+
  scale_x_continuous(breaks = NULL) + scale_y_continuous(breaks = NULL) +
  labs(x = "", y = "") + theme(legend.position = "bottom", 
                               panel.background = element_blank())

enter image description here

If one wants to compare all years I suggest doing it without text since it will be very cluttered:

homicide %>%
  filter(Crime.Type == "Murder or Manslaughter") %>%
  group_by(State, Year) %>%
  summarise(n = n()) %>%
  mutate(state = tolower(State)) %>%
  ggplot(aes(map_id = state)) + 
  geom_map(aes(fill = n),  color= "black", map = fifty_states) + 
  expand_limits(x = fifty_states$long, y = fifty_states$lat) +
  coord_map() +
  scale_x_continuous(breaks = NULL) + scale_y_continuous(breaks = NULL) +
  labs(x = "", y = "") + theme(legend.position = "bottom", 
                               panel.background = element_blank())+
  facet_wrap(~Year, ncol = 5)

enter image description here

One can see not much has changed during the years.

I trust a more informative plot is:

homocide %>%
  filter(Crime.Type == "Murder or Manslaughter") %>%
  group_by(State, Year) %>%
  summarise(n = n()) %>%
  mutate(state = tolower(State)) %>%
  ggplot()+
  geom_line(aes(x = Year, y = n))+
  facet_wrap(~state, ncol = 6, scales= "free_y")+
  theme_bw()

enter image description here

like image 95
missuse Avatar answered Nov 11 '22 08:11

missuse