Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Embed URL


Subversion checkout URL

You can clone with
Download ZIP
basic map
doInstall <- TRUE
toInstall <- c("maps", "ggplot2")
if(doInstall){install.packages(toInstall, repos = "")}
lapply(toInstall, library, character.only = TRUE)
Prison <- read.csv("")
all_states <- map_data("state")
Prison$region <- Prison$stateName
Total <- merge(all_states, Prison, by="region")
Total <- Total[Total$region!="district of columbia",]
p <- ggplot()
p <- p + geom_polygon(data=Total, aes(x=long, y=lat, group = group, fill=Total$bwRatio),colour="white"
) + scale_fill_continuous(low = "thistle2", high = "darkred", guide="colorbar")
P1 <- p + theme_bw() + labs(fill = "Black to White Incarceration Rates \n Weighted by Relative Population"
,title = "State Incarceration Rates by Race, 2010", x="", y="")
P1 + scale_y_continuous(breaks=c()) + scale_x_continuous(breaks=c()) + theme(panel.border = element_blank())

Thanx for the write up. FYI, CSV file does not exist anymore. But I got what I was looking for.






Thank you!Really nice example. I would suggest that first remove the 'district of columbia' and later merge the data. Remove after merging in some datasets give some anomalies to the visualization.


I had to make a few tweaks to my code to get this to work. (I also forked this gist to show my new code.)

For example, instead of:
Total <- merge(all_states, Prison, by="region")
I had to do:
Total <- merge(all_states, Prison, all=TRUE)

However, after doing that, my map had a bunch of lines running through it. To fix it, I found the following to be helpful (tweaked from

loading packages
#for maps
#help(package="maps") #help files if needed

#for plotting data
#help(package="ggplot2") #help files if needed

#this package loads tables faster than merge
#help(package="data.table") #if you need help with the package later

#to get fancy colors for graphing
#can see some color palettes here:
#help(package="RColorBrewer") #if you need help with the package later

#Matching state map data frame to Prison data frame
#setting keys to match the two data frames (all_states and Prison)
all_states <- data.table(map_data('state'))
Prison <- data.table(Prison)
#now merging the two data frames together based on those keys
map.df <- all_states[Prison]

#now creating the state map
ggplot(map.df, aes(x=long, y=lat, group=group, fill=bwRatio)) +
labs(fill="Black to White Incarceration Rates \n Weighted by Relative Population",
title="State Incarceration Rates by Race, 2010",x="",y="")+theme_bw()


Amanda, where did you find the prison data?


@jmorten - I couldn't find the prison data - but I used the same code concept for some other data that I was working with. I only listed the code using the Prison data here to stay consistent with the original example.


It appears you can fix the "splintered map/random lines in the map" issue simply by ordering your variables by the "order" variable in all_states after your last merger.
I.e. just insert Total <- Total[order(Total$order),] before running the plotting functions. (see, last answer)

The main difference using the "all = TRUE" argument in the initial merger (Total <- merge(all_states, Prison, all=TRUE)) seems to be that if you DON'T set "all = TRUE" and you are missing data for single states they will be shown as opaque, whereas if you do set "all = TRUE" the states will be inserted but not colored.

Thanks @amandamasonsingh for the code revisions, pointing to the stackoverflow thread, and highlighting the "all = TRUE" issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.