Browse Source

statebins reimagined

master
boB Rudis 5 years ago
parent
commit
5c63e18785
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 10
      DESCRIPTION
  2. 9
      NAMESPACE
  3. 3
      NEWS.md
  4. 2
      R/aaa.R
  5. 106
      R/statebins-continuous.R
  6. 119
      R/statebins-manual.R
  7. 5
      R/statebins-package.R
  8. 140
      R/statebins.R
  9. 24
      R/theme-statebin.R
  10. 12
      R/util.R
  11. 236
      README.Rmd
  12. BIN
      README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-1.png
  13. BIN
      README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-2.png
  14. BIN
      README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-3.png
  15. BIN
      README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-4.png
  16. BIN
      README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-5.png
  17. BIN
      README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-6.png
  18. 268
      README.md
  19. BIN
      README_files/figure-gfm/unnamed-chunk-3-1.png
  20. BIN
      README_files/figure-gfm/unnamed-chunk-3-2.png
  21. BIN
      README_files/figure-gfm/unnamed-chunk-3-3.png
  22. BIN
      README_files/figure-gfm/unnamed-chunk-3-4.png
  23. BIN
      README_files/figure-gfm/unnamed-chunk-3-5.png
  24. BIN
      README_files/figure-gfm/unnamed-chunk-3-6.png
  25. BIN
      README_files/figure-gfm/unnamed-chunk-4-1.png
  26. 80
      man/statebins.Rd
  27. 74
      man/statebins_continuous.Rd
  28. 83
      man/statebins_manual.Rd
  29. 18
      man/theme_statebins.Rd
  30. 52
      tmp/election2012.csv
  31. BIN
      tmp/household.gif
  32. BIN
      tmp/household2000.png
  33. BIN
      tmp/household2001.png
  34. BIN
      tmp/household2002.png
  35. BIN
      tmp/household2003.png
  36. BIN
      tmp/household2004.png
  37. BIN
      tmp/household2005.png
  38. BIN
      tmp/household2006.png
  39. BIN
      tmp/household2007.png
  40. BIN
      tmp/household2008.png
  41. BIN
      tmp/household2009.png
  42. BIN
      tmp/household2010.png
  43. BIN
      tmp/household2011.png
  44. BIN
      tmp/household2012.png
  45. BIN
      tmp/statebins-composite.png

10
DESCRIPTION

@ -2,7 +2,7 @@ Package: statebins
Type: Package
Title: Create 'U.S.' Uniform Square State Cartogram Heatmaps
Version: 1.3.0
Date: 2018-11-14
Date: 2017-11-14
Author: Bob Rudis (bob@rud.is)
Maintainer: Bob Rudis <bob@rud.is>
Description: Cartogram heatmaps are an alternative to choropleth maps for 'USA' States
@ -17,12 +17,12 @@ URL: https://github.com/hrbrmstr/statebins
BugReports: https://github.com/hrbrmstr/statebins/issues
License: MIT + file LICENSE
Suggests:
testthat
testthat,
viridis,
RColorBrewer
Depends:
R (>= 3.2.0),
Imports:
ggplot2 (>= 2.2.0),
scales (>= 0.5.0),
viridis,
RColorBrewer (>= 1.1-2)
scales (>= 0.5.0)
RoxygenNote: 6.0.1

9
NAMESPACE

@ -1,11 +1,9 @@
# Generated by roxygen2: do not edit by hand
export(statebins)
export(statebins_continuous)
export(statebins_manual)
import(RColorBrewer)
import(viridis)
export(theme_statebins)
importFrom(ggplot2,aes)
importFrom(ggplot2,aes_)
importFrom(ggplot2,aes_string)
importFrom(ggplot2,coord_equal)
importFrom(ggplot2,element_blank)
@ -17,17 +15,14 @@ importFrom(ggplot2,geom_tile)
importFrom(ggplot2,ggplot)
importFrom(ggplot2,ggplotGrob)
importFrom(ggplot2,ggtitle)
importFrom(ggplot2,guide_legend)
importFrom(ggplot2,guides)
importFrom(ggplot2,labs)
importFrom(ggplot2,rel)
importFrom(ggplot2,scale_color_manual)
importFrom(ggplot2,scale_fill_brewer)
importFrom(ggplot2,scale_fill_gradientn)
importFrom(ggplot2,scale_fill_manual)
importFrom(ggplot2,scale_x_continuous)
importFrom(ggplot2,scale_y_continuous)
importFrom(ggplot2,scale_y_reverse)
importFrom(ggplot2,theme)
importFrom(ggplot2,theme_bw)
importFrom(scales,alpha)

3
NEWS.md

@ -1,5 +1,8 @@
# statebins 1.3.0
* Added support for `VI`/`Virgin Islands`
* Supports auto-computation of when to use light & dark label colors
* New `theme_statebins()`
* Completely re-designed the interface and will not be providing backwards-compatibility.
# statebins 1.2.2
* CRAN update

2
R/aaa.R

@ -3,7 +3,7 @@ state_coords <- structure(list(abbrev = c("AL", "AK", "AZ", "AR", "CA", "CO",
"KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE",
"NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA",
"RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY",
"PR", "VI"),
"PR", "VI", "NYC"),
state = c("Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "District of Columbia",
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois",

106
R/statebins-continuous.R

@ -1,106 +0,0 @@
#' Create a new ggplot-based "statebin" chart for USA states (continuous scale)
#'
#' \code{statebins()} creates "statebin" charts in the style of \url{http://bit.ly/statebins}
#'
#' This version uses a continuous scale based on \code{RColorBrewer} scales
#' (passing in a 6 element \code{RColorBrewer} palette to \code{scale_fill_gradientn}).
#'
#' The function minimally expects the caller to pass in a data frame that:
#'
#' \itemize{
#' \item has one column of all state abbreviationis (all caps, including \code{DC} &
#' \code{PR} ) or a column of state names (standard capitalization) named \code{state}
#' \item has another column of values named \code{value}
#' }
#'
#' Doing so will create a "statebin" chart with 5 breaks and return a \code{ggplot2} object.
#'
#' You can use a different column for the state names and values by changing \code{state_col}
#' and \code{value_col} accordingly.
#'
#' To add a title, change \code{plot_title} to anything but an empty atomic string vector (i.e. \code{""})
#' and set \code{title_position} to "\code{top}" or "\code{bottom}". Choosing "\code{bottom}"
#' will cause \code{statebins} to use the X axis title placeholder.
#'
#' @param state_data data frame of states and values to plot
#' @param state_col column name in \code{state_data} that has the states. no duplicates
#' and can be names (e.g. "\code{Maine}") or abbreviatons (e.g. "\code{ME}")
#' @param value_col column name in \code{state_data} that holds the values to be plotted
#' @param text_color default "\code{black}". Size 1 for global color across all tiles or
#' a vector of colors the same length as the number of states you passed in.
#' Use the sort order for the states as they are sorted before being plotted.
#' @param font_size font size (default = \code{3})
#' @param state_border_col default "\code{white}" - this creates the "spaces" between boxes
#' @param legend_title title for the legend
#' @param legend_position "\code{none}", "\code{top}", "\code{left}", "\code{right}" or
#' "\code{bottom}" (defaults to "\code{top}")
#' @param brewer_pal which named \code{RColorBrewer} palette to use (defaults to "PuBu")
#' @param plot_title title for the plot
#' @param title_position where to put the title ("\code{bottom}" or "\code{top}" or ""
#' for none); if "\code{bottom}", you get back a grob vs a ggplot object
#' @return ggplot2 object or grob
#' @export
#' @examples
#' \dontrun{
#' data(USArrests)
#' USArrests$state <- rownames(USArrests)
#' statebins_continuous(USArrests, value_col="Murder", text_color="black", font_size=3,
#' legend_title = "Murder", legend_position="bottom")
#' }
statebins_continuous <- function(state_data, state_col="state", value_col="value",
text_color="black", font_size=3,
state_border_col="white",
legend_title="Legend", legend_position="top",
brewer_pal="PuBu", plot_title="", title_position="bottom") {
if (!title_position %in% c("", "top", "bottom")) {
stop("'title_position' must be either blank, 'top' or 'bottom'")
}
if (!legend_position %in% c("", "none", "top", "bottom")) {
stop("'legend_position' must be either blank, 'none', 'top' or 'bottom'")
}
state_data <- data.frame(state_data, stringsAsFactors=FALSE)
if (max(nchar(state_data[,state_col])) == 2) {
merge.x <- "abbrev"
} else {
merge.x <- "state"
}
state_data <- validate_states(state_data, state_col, merge.x)
st.dat <- merge(state_coords, state_data, by.x=merge.x, by.y=state_col, all.y=TRUE)
gg <- ggplot(st.dat, aes_string(x="col", y="row", label="abbrev"))
gg <- gg + geom_tile(aes_string(fill=value_col))
gg <- gg + geom_tile(color=state_border_col,
aes_string(fill=value_col), size=3, show.legend=FALSE)
gg <- gg + geom_text(color=text_color, size=font_size)
gg <- gg + scale_y_reverse()
gg <- gg + scale_fill_gradientn(colours = brewer.pal(6, brewer_pal), name=legend_title)
gg <- gg + coord_equal()
gg <- gg + labs(x=NULL, y=NULL, title=NULL)
gg <- gg + theme_bw()
gg <- gg + theme(legend.position=legend_position)
gg <- gg + theme(panel.border=element_blank())
gg <- gg + theme(panel.grid=element_blank())
gg <- gg + theme(panel.background=element_blank())
gg <- gg + theme(axis.ticks=element_blank())
gg <- gg + theme(axis.text=element_blank())
if (plot_title != "") {
if (title_position == "bottom") {
gg <- gg + labs(x=plot_title)
gg <- gg + theme(axis.text.x=element_text(hjust=0.5, size=ggplot2::rel(1.2), angle=0))
} else {
gg <- gg + ggtitle(plot_title)
}
}
return(gg)
}

119
R/statebins-manual.R

@ -1,119 +0,0 @@
#' Create a new ggplot-based "statebin" chart for USA states (manually colored)
#'
#' \code{statebins()} creates "statebin" charts in the style of \url{http://bit.ly/statebins}
#'
#' This version uses manual colors (i.e. pass in a column that defines the color per-state)
#'
#' The function minimally expects the caller to pass in a data frame that:
#'
#' \itemize{
#' \item has one column of all state abbreviationis (all caps, including \code{DC} &
#' \code{PR} or a column of state names (standard capitalization) named \code{state}
#' \item has another column of colors named \code{color}
#' }
#'
#' Doing so will create a "statebin" chart with the colors specified as a ggplot2 object.
#'
#' You can use a different column for the state names and colors by changing \code{state_col}
#' and \code{color_col} accordingly.
#'
#' To add a title, change \code{plot_title} to anything but an empty atomic string vector (i.e. \code{""})
#' and set \code{title_position} to "\code{top}" or "\code{bottom}". Choosing "\code{bottom}"
#' will cause \code{statebins} to use the X axis title placeholder.
#'
#' @param state_data data frame of states and values to plot
#' @param state_col column name in \code{state_data} that has the states. no duplicates
#' and can be names (e.g. "\code{Maine}") or abbreviatons (e.g. "\code{ME}")
#' @param color_col column name in \code{state_data} that holds the colors to be used
#' @param text_color default "\code{black}". Size 1 for global color across all tiles or
#' a vector of colors the same length as the number of states you passed in.
#' Use the sort order for the states as they are sorted before being plotted.
#' @param font_size font size (default = \code{3})
#' @param state_border_col default "\code{white}" - this creates the "spaces" between boxes
#' @param labels labels for the legend (should be the same number as distinct colors in
#' \code{color_col}); \code{NULL} == no labels/legend
#' @param legend_title title for the legend
#' @param legend_position "\code{none}", "\code{top}", "\code{left}", "\code{right}" or
#' "\code{bottom}" (defaults to "\code{top}")
#' @param plot_title title for the plot
#' @param title_position where to put the title ("\code{bottom}" or "\code{top}" or ""
#' for none); if "\code{bottom}", you get back a grob vs a ggplot object
#' @return ggplot2 object or grob
#' @export
#' @examples
#' \dontrun{
#' library(httr)
#' library(dplyr)
#' election_2012 <-
#' GET("https://raw.githubusercontent.com/hrbrmstr/statebins/master/tmp/election2012.csv")
#' results <- read.csv(textConnection(content(election_2012, as="text")),
#' header=TRUE, stringsAsFactors=FALSE)
#' results <- results %>%
#' mutate(color=ifelse(is.na(Obama), "#2166ac", "#b2182b")) %>%
#' select(state, color)
#' results %>%
#' statebins_manual(font_size=4,
#' text_color = "white", labels=c("Romney", "Obama"),
#' legend_position="right", legend_title="Winner")
#' }
statebins_manual <- function(state_data, state_col="state", color_col="color",
text_color="black", font_size=3,
state_border_col="white", labels=NULL,
legend_title="Legend", legend_position="top",
plot_title="", title_position="bottom") {
if (!title_position %in% c("", "top", "bottom")) {
stop("'title_position' must be either blank, 'top' or 'bottom'")
}
state_data <- data.frame(state_data, stringsAsFactors=FALSE)
if (max(nchar(state_data[,state_col])) == 2) {
merge.x <- "abbrev"
} else {
merge.x <- "state"
}
state_data <- validate_states(state_data, state_col, merge.x)
st.dat <- merge(state_coords, state_data, by.x=merge.x, by.y=state_col, all.y=TRUE)
gg <- ggplot(st.dat, aes_string(x="col", y="row", label="abbrev"))
gg <- gg + geom_tile(aes_string(fill=color_col))
gg <- gg + geom_tile(color=state_border_col, aes_string(fill="color"),
size=2, show.legend=FALSE)
gg <- gg + geom_text(color=text_color, size=font_size)
gg <- gg + scale_y_reverse()
if (is.null(labels)) {
gg <- gg + scale_fill_manual(values=unique(st.dat[,color_col]))
legend_position = "none"
} else {
gg <- gg + scale_fill_manual(values=unique(st.dat[,color_col]),
labels=labels, name=legend_title)
}
gg <- gg + coord_equal()
gg <- gg + labs(x=NULL, y=NULL, title=NULL)
gg <- gg + theme_bw()
gg <- gg + theme(legend.position=legend_position)
gg <- gg + theme(panel.border=element_blank())
gg <- gg + theme(panel.grid=element_blank())
gg <- gg + theme(panel.background=element_blank())
gg <- gg + theme(axis.ticks=element_blank())
gg <- gg + theme(axis.text=element_blank())
if (plot_title != "") {
if (title_position == "bottom") {
gg <- gg + labs(x=plot_title)
gg <- gg + theme(axis.text.x=element_text(hjust=0.5, size=ggplot2::rel(1.2), angle=0))
} else {
gg <- gg + ggtitle(plot_title)
}
}
return(gg)
}

5
R/statebins-package.R

@ -4,12 +4,11 @@
#' @name statebins-package
#' @docType package
#' @author Bob Rudis (bob@@rud.is)
#' @import RColorBrewer viridis
#' @importFrom scales alpha
#' @importFrom ggplot2 ggplot geom_tile scale_fill_manual guides geom_tile ggplotGrob
#' @importFrom ggplot2 geom_point geom_text scale_color_manual guides theme labs
#' @importFrom ggplot2 scale_x_continuous scale_y_continuous coord_equal theme_bw
#' @importFrom ggplot2 aes guide_legend element_rect element_blank element_text
#' @importFrom ggplot2 aes_string scale_y_reverse scale_fill_gradientn
#' @importFrom ggplot2 aes element_rect element_blank element_text
#' @importFrom ggplot2 aes_string aes_
#' @importFrom ggplot2 scale_fill_brewer ggtitle rel
NULL

140
R/statebins.R

@ -1,82 +1,52 @@
#' Create a new ggplot-based "statebin" chart for USA states (discrete scale)
#' Create a new ggplot-based "statebin" chart for USA states/territories
#'
#' \code{statebins()} creates "statebin" charts in the style of \url{http://bit.ly/statebins}
#' Pass in a data frame and get back a square choropleth.
#'
#' This version uses discrete \code{RColorBrewer} scales, binned by the "breaks" parameter.
#' The `state_col` and `value_col` parameters default to `state` and `value`. That means
#' if you name the columns you want to plot with those names, you can forego passing them
#' in. Othersise, use `"strings"`.
#'
#' The function minimally expects the caller to pass in a data frame that:
#' A _handy_ feature of this function is that you can specify a `dark_label` color
#' and a `light_label` color. What does that mean? Well, you also pass in the
#' color scale function you're going to use and `statebins` will apply it and use
#' that information to determine what the tile color is and --- if it's "dark" it will
#' use the `light_label` and if it's "light" it will use the `dark_label` color. That
#' means the labels will never blend in to the background (as long as you specify
#' decent label colors).
#'
#' \itemize{
#' \item has one column of all state abbreviationis (all caps, including \code{DC} &
#' \code{PR} or a column of state names (standard capitalization) named \code{state}
#' \item has another column of values named \code{value}
#' }
#'
#' Doing so will create a "statebin" chart with 5 breaks and return a ggplot2 object.
#'
#' You can use a different column for the state names and values by changing \code{state_col}
#' and \code{value_col} accordingly.
#'
#' To add a title, change \code{plot_title} to anything but an empty atomic string vector (i.e. \code{""})
#' and set \code{title_position} to "\code{top}" or "\code{bottom}". Choosing "\code{bottom}"
#' will cause \code{statebins} to use the X axis title as the title.
#' You can customize the scale function you pass in by using name parameters. All named
#' parameters not used by `statebins()` itself get passed to the scale function.
#'
#' @md
#' @param state_data data frame of states and values to plot
#' @param state_col column name in \code{state_data} that has the states. no duplicates
#' and can be names (e.g. "\code{Maine}") or abbreviatons (e.g. "\code{ME}")
#' @param value_col column name in \code{state_data} that holds the values to be plotted
#' @param text_color default "\code{black}". Size 1 for global color across all tiles or
#' a vector of colors the same length as the number of states you passed in.
#' Use the sort order for the states as they are sorted before being plotted.
#' @param dark_label,light_label dark/light label colors. The specified color will be used
#' when the algorithm determines labels should be inverted.
#' @param font_size font size (default = \code{3})
#' @param state_border_col default "\code{white}" - this creates the "spaces" between boxes
#' @param breaks a single number (greater than or equal to 2) giving the number of intervals
#' into which data values are to be cut.
#' @param labels labels for the levels \code{breaks}
#' @param legend_title title for the legend
#' @param legend_position "\code{none}", "\code{top}", "\code{left}", "\code{right}" or
#' "\code{bottom}" (defaults to "\code{top}")
#' @param palette either "`brewer`" or "`viridis`". Choose `viridis` if you have
#' 10 or more levels (more than 10 is not recommended). You can choose which
#' viridis palette option (e.g. "magma") with `viridis_pal`.
#' @param brewer_pal which named \code{RColorBrewer} palette to use (defaults to "PuBu");
#' used when `palette` is `brewer`.
#' @param viridis_pal which named \code{viridis} palette option to use (default if `NULL`);
#' used when `palette` is `viridis`.
#' @param plot_title title for the plot
#' @param title_position where to put the title ("\code{bottom}" or "\code{top}" or ""
#' for none); if "\code{bottom}", you get back a grob vs a ggplot object
#' @return ggplot2 object or grob
#' @param state_border_size border size
#' @param ggplot2_scale_function ggplot2 scale function to use. Defaults to `scale_fill_distiller`
#' since you're likely passing in continuous data when you shouldn't be :-)
#' @return ggplot2 object
#' @export
#' @examples
#' \dontrun{
#' data(USArrests)
#'
#' USArrests$state <- rownames(USArrests)
#' statebins(USArrests, value_col="Assault", text_color="black", font_size=3,
#' legend_title = "Assault", legend_position="bottom")
#' }
statebins <- function(state_data, state_col="state", value_col="value",
text_color="black", font_size=3,
state_border_col="white",
breaks=5, labels=1:5,
legend_title="Legend", legend_position="top",
palette=c("brewer", "viridis"), viridis_pal=NULL,
brewer_pal="palette",
plot_title="", title_position="bottom") {
palette <- match.arg(trimws(tolower(palette)), c("brewer", "viridis"))
# if (breaks <= 0 | breaks > 10) {
# stop("'breaks' must be between 0 & 10")
# }
if (!title_position %in% c("", "top", "bottom")) {
stop("'title_position' must be either blank, 'top' or 'bottom'")
}
#' statebins(USArrests, value_col="Assault", name = "Assault") +
#' theme_statebins(legend_position="right")
statebins <- function(state_data,
state_col="state", value_col="value",
dark_label = "black", light_label = "white", font_size=3,
state_border_col="white", state_border_size=2,
ggplot2_scale_function=ggplot2::scale_fill_distiller,
...) {
state_data <- data.frame(state_data, stringsAsFactors=FALSE)
if (max(nchar(state_data[,state_col])) == 2) {
if (max(nchar(state_data[,state_col])) <= 3) {
merge.x <- "abbrev"
} else {
merge.x <- "state"
@ -84,45 +54,25 @@ statebins <- function(state_data, state_col="state", value_col="value",
state_data <- validate_states(state_data, state_col, merge.x)
st.dat <- merge(state_coords, state_data, by.x=merge.x, by.y=state_col, all.y=TRUE)
st.dat$fill_color <- cut(st.dat[, value_col], breaks=breaks, labels=labels)
st.dat <- merge(state_coords, state_data, by.x=merge.x, by.y=state_col, all.y=TRUE,
sort=TRUE)
gg <- ggplot(st.dat, aes_string(x="col", y="row", label="abbrev"))
gg <- gg + geom_tile(aes_string(fill="fill_color"))
gg <- gg + geom_tile(color=state_border_col, aes_string(fill="fill_color"),
size=2, show.legend=FALSE)
gg <- gg + geom_text(color=text_color, size=font_size)
gg <- ggplot()
gg <- gg + geom_tile(data = st.dat,
aes_string(x = "col", y = "row", fill = value_col),
color = state_border_col, size = state_border_size)
gg <- gg + scale_y_reverse()
if (palette == "brewer") {
gg <- gg + scale_fill_brewer(palette=brewer_pal, name=legend_title, drop=FALSE)
} else if (palette == "viridis") {
if (is.null(viridis_pal)) viridis_pal <- "D"
gg <- gg + scale_fill_viridis(discrete=TRUE, option=viridis_pal, name=legend_title, drop=FALSE)
}
gg <- gg + ggplot2_scale_function(...)
gg <- gg + coord_equal()
gg <- gg + labs(x=NULL, y=NULL, title=NULL)
gg <- gg + theme_bw()
gg <- gg + theme(legend.position=legend_position)
gg <- gg + theme(panel.border=element_blank())
gg <- gg + theme(panel.grid=element_blank())
gg <- gg + theme(panel.background=element_blank())
gg <- gg + theme(axis.ticks=element_blank())
gg <- gg + theme(axis.text=element_blank())
if (plot_title != "") {
gg <- gg + labs(x = NULL, y = NULL)
if (title_position == "bottom") {
gg <- gg + labs(x=plot_title)
gg <- gg + theme(axis.text.x=element_text(hjust=0.5, size=ggplot2::rel(1.2), angle=0))
} else {
gg <- gg + ggtitle(plot_title)
}
gb <- ggplot2::ggplot_build(gg)
}
gg <- gg + geom_text(data = st.dat,
aes_string(x = "col", y = "row", label = "abbrev"),
color = .sb_invert(gb$data[[1]]$fill, dark_label, light_label),
size = font_size)
return(gg)
gg
}

24
R/theme-statebin.R

@ -0,0 +1,24 @@
#' Base statebins theme
#'
#' Clears out most of the cruft. Builds off of `theme_bw()`
#'
#' @md
#' @param legend_position fills in `legend.position`
#' @param base_family,base_size,base_line_size,base_rect_size same as `theme_bw()`
#' @export
theme_statebins <- function(legend_position="bottom",
base_size = 11, base_family = "",
base_line_size = base_size/22,
base_rect_size = base_size/22) {
gg <- theme_bw(base_family = base_family, base_size = base_size,
base_line_size = base_line_size, base_rect_size = base_rect_size)
gg <- gg + theme(panel.border=element_blank())
gg <- gg + theme(panel.grid=element_blank())
gg <- gg + theme(panel.background=element_blank())
gg <- gg + theme(axis.ticks=element_blank())
gg <- gg + theme(axis.text=element_blank())
gg <- gg + theme(plot.title=element_text(hjust=0.5))
gg <- gg + theme(axis.title.x=element_text(hjust=0.5))
gg <- gg + theme(legend.position=legend_position)
gg
}

12
R/util.R

@ -1,14 +1,14 @@
invert <- function(hexColor, darkColor="black", lightColor="white") {
.sb_invert <- function(hex_color, dark_color="black", light_color="white") {
hexColor <- gsub("#", "", hexColor)
hex_color <- gsub("#", "", hex_color)
R <- as.integer(paste("0x", substr(hexColor,1,2), sep=""))
G <- as.integer(paste("0x", substr(hexColor,3,4), sep=""))
B <- as.integer(paste("0x", substr(hexColor,5,6), sep=""))
R <- as.integer(paste("0x", substr(hex_color,1,2), sep=""))
G <- as.integer(paste("0x", substr(hex_color,3,4), sep=""))
B <- as.integer(paste("0x", substr(hex_color,5,6), sep=""))
YIQ <- ((R*299) + (G*587) + (B*114)) / 1000
return(ifelse(YIQ >= 128, darkColor, lightColor))
return(ifelse(YIQ >= 128, dark_color, light_color))
}

236
README.Rmd

@ -1,5 +1,7 @@
---
output: rmarkdown::github_document
editor_options:
chunk_output_type: console
---
```{r echo=FALSE, message=FALSE, warning=FALSE, error=FALSE, include=FALSE}
knitr::opts_chunk$set(message=FALSE, warning=FALSE, fig.retina=2)
@ -14,14 +16,8 @@ Create 'U.S.' Uniform Square State Cartogram Heatmaps
The following functions are implemented:
- `statebins` - creates "statebin" charts in the style of http://bit.ly/statebins - This version uses discrete `RColorBrewer` scales, binned by the "breaks" parameter.
- `statebins_continuous` - creates "statebin" charts in the style of http://bit.ly/statebins - This version uses a continuous scale based on `RColorBrewer` scales (passing in a 6 element `RColorBrewer` palette to `scale_fill_gradientn`).
- `statebins_manual` - creates "statebin" charts using manually specified colors in a column
## TODO
- The current version is usable, but I think the plot margins and the legends need work
- Apply algorithm to switch to light-on-dark depending on the background tile color
- `statebins`: Creates "statebin" charts in the style of http://bit.ly/statebins
- `theme_statebins`: Base statebins theme
## Installation
@ -41,182 +37,94 @@ library(tidyverse)
packageVersion("statebins")
# the original wapo data
cols(
fipst = col_character(), stab = col_character(), state = col_character(), workers1994 = col_integer(), workers1995 = col_integer(), workers1996 = col_integer(), workers1997 = col_integer(), workers1998 = col_integer(), workers1999 = col_integer(), workers2000 = col_integer(), workers2001 = col_integer(), workers2002 = col_integer(), workers2003 = col_integer(), workers2004 = col_integer(), workers2005 = col_integer(), workers2006 = col_integer(), workers2007 = col_integer(), workers2008 = col_integer(), workers2009 = col_integer(), workers2010 = col_integer(), workers2011 = col_integer(), workers2012 = col_integer(), workers2013 = col_integer(),
share_cut1994 = col_double(), share_cut1995 = col_double(), share_cut1996 = col_double(), share_cut1997 = col_double(), share_cut1998 = col_double(), share_cut1999 = col_double(), share_cut2000 = col_double(), share_cut2001 = col_double(), share_cut2002 = col_double(), share_cut2003 = col_double(), share_cut2004 = col_double(), share_cut2005 = col_double(), share_cut2006 = col_double(), share_cut2007 = col_double(), share_cut2008 = col_double(), share_cut2009 = col_double(), share_cut2010 = col_double(), share_cut2011 = col_double(), share_cut2012 = col_double(), share_cut2013 = col_double(),
avgshare = col_double(), avgshare94_00 = col_double(), avgshare01_07 = col_double(), avgshare08_12 = col_double()
) -> wapo_cols
adat <- read_csv("http://www.washingtonpost.com/wp-srv/special/business/states-most-threatened-by-trade/states.csv?cache=1",
col_types = wapo_cols)
gg <- statebins(
adat, "state", "avgshare94_00",
breaks = 4,
labels = c("0-1", "1-2", "2-3", "3-4"),
legend_title = "Share of workforce with jobs lost or threatened by trade",
font_size = 3,
brewer_pal = "Blues",
text_color = "black",
plot_title = "1994-2000",
title_position = "bottom"
)
gg
adat <- suppressMessages(read_csv("http://www.washingtonpost.com/wp-srv/special/business/states-most-threatened-by-trade/states.csv?cache=1"))
mutate(
adat,
share = cut(avgshare94_00, breaks = 4, labels = c("0-1", "1-2", "2-3", "3-4"))
) %>%
statebins(
value_col = "share",
ggplot2_scale_function = scale_fill_brewer,
name = "Share of workforce with jobs lost or threatened by trade"
) +
labs(title = "1994-2000") +
theme_statebins()
# continuous scale, legend on top
gg2 <- statebins_continuous(
adat, "state", "avgshare01_07",
legend_title="Share of workforce with jobs lost or threatened by trade", legend_position="top",
brewer_pal="OrRd", text_color="black", font_size=3,
plot_title="2001-2007", title_position="bottom"
)
statebins(
adat, value_col = "avgshare01_07",
name = "Share of workforce with jobs lost or threatened by trade",
palette = "OrRd", direction = 1
) +
labs(x="2001-2007") +
theme_statebins(legend_position="top")
gg2
# continuous scale, no legend
gg3 <- statebins_continuous(
adat, "state", "avgshare08_12",
legend_title="States", legend_position="none",
brewer_pal="Purples", text_color="black", font_size=3,
plot_title="2008-2012", title_position="bottom"
)
statebins(adat, value_col = "avgshare08_12", palette = "Purples") +
labs(x="2008-2010") +
theme_statebins(legend_position = "none")
gg3
# mortality (only to show PR and using a data.table)
# mortality data (has Puerto Rico)
# from: http://www.cdc.gov/nchs/fastats/state-and-territorial-data.htm
cols(
state = col_character(),
births = col_integer(),
fertility_rate = col_double(),
deaths = col_integer(),
death_rate = col_double()
) -> deaths_cols
dat <- suppressMessages(read_csv("http://datadrivensecurity.info/data/deaths.csv"))
dat <- read_csv("http://datadrivensecurity.info/data/deaths.csv", col_types=deaths_cols)
statebins_continuous(dat, "state", "death_rate", legend_title="Per 100K pop",
plot_title="Mortality Rate (2010)")
statebins(dat, value_col = "death_rate", name="Per 100K pop") +
labs(title="Mortality Rate (2010)") +
theme_statebins()
# fertility (only to show tbl_dt)
# fertility data
statebins_continuous(dat, "state", "fertility_rate", legend_title="Per 100K pop",
plot_title="Fertility Rate (2010)", brewer_pal="PuBuGn")
statebins(dat, value_col="fertility_rate", name="Per 100K pop", palette="PuBuGn") +
labs(title="Fertility Rate (2010)") +
theme_statebins()
# manual - perhaps good for elections?
library(httr)
library(dplyr)
election_2012 <- GET("https://raw.githubusercontent.com/hrbrmstr/statebins/master/tmp/election2012.csv")
read.csv(
textConnection(content(election_2012, as="text")),
header=TRUE, stringsAsFactors=FALSE
) %>%
mutate(color=ifelse(is.na(Obama), "#2166ac", "#b2182b")) %>%
select(state, color) -> results
statebins_manual(
results,
font_size=4, text_color = "white",
labels=c("Romney", "Obama"), legend_position="right", legend_title="Winner"
)
election_2012 <- suppressMessages(read_csv("https://raw.githubusercontent.com/hrbrmstr/statebins/master/tmp/election2012.csv"))
# or, more like the one in the WaPo article; i might be picking the wrong columns here. it's just for an example
sb <- function(col, title) {
mutate(election_2012, value = ifelse(is.na(Obama), "Romney", "Obama")) %>%
statebins(
adat, "state", col, brewer_pal="Blues", text_color="black",
legend_position="none", font_size=3, plot_title=title,
breaks=4, labels=1:4
)
}
```
```{r eval=FALSE}
# cheating and using <table> to arrange them below and also making a WaPo-like legend,
# since mucking with grid graphics margins/padding was not an option time-wise at the moment
sb("avgshare94_00", "1994-2000")
sb("avgshare01_07", "2001-2007")
sb("avgshare08_12", "2008-2012")
font_size=4, dark_label = "white", light_label = "white",
ggplot2_scale_function = scale_fill_manual,
name = "Winner",
values = c(Romney = "#2166ac", Obama = "#b2182b")
) +
theme_statebins()
```
<!-- uncomment the following and add backticks where appropriate and remove the reference to -->
<!-- the static image when the rmarkdown output is HTML and this will work fine. github does not render the markdown properly -->
<!--
<span style="font-size:17px; color:#333;">Share of workforce with jobs lost or threatened by trade</span><br/>
<table style="width:200px" cellpadding=0, cellspacing=0><tr style="line-height:10px">
<td width="25%" style="background:#EFF3FF;">&nbsp;</td>
<td width="25%" style="background:#BDD7E7;">&nbsp;</td>
<td width="25%" style="background:#6BAED6;">&nbsp;</td>
<td width="25%" style="background:#2171B5;">&nbsp;</td></tr>
<tr><td colspan=2 align="left" style="font-size:14px">Smallest share</td><td colspan=2 align="right" style="font-size:14px">Largest</td></tr>
</table>
### All the "states"
<table width="100%" cellpadding="0" cellspacing="0">
<tr><td width="50%">
`statebins` now has PR, VI & NYC (by name or abbreviation) so you can use them, too:
{r f1994, echo=FALSE, fig.width=6, fig.height=5}
sb("avgshare94_00", "1994-2000")
</td><td width="50%">
{r f2001, echo=FALSE, fig.width=6, fig.height=5, results='asis'}
sb("avgshare01_07", "2001-2007")
</td></tr><tr><td width="50%">
{r f2008, echo=FALSE, fig.width=6, fig.height=5, results='asis'}
sb("avgshare08_12", "2008-2012")
</td><td width="50%"> &nbsp; </td></tr></table>
-->
<center>![img](./tmp/statebins-composite.png)</center>
And, we'll throw in a gratuitous animation for good measure:
```{r eval=FALSE}
library(magick)
# data set from StatsAmerica - http://www.statsamerica.org/profiles/sip_index.html
# median household income from the ACS survey
miacs <- read.csv("http://datadrivensecurity.info/data/median-income-acs.csv",
header=TRUE, stringsAsFactors=FALSE)
# generate frames based on year
purrr::map(unique(miacs$year), function(year) {
cat(".")
fig <- magick::image_graph(res=144)
rng <- floor(range(miacs[miacs$year==year,]$mh_inc))
statebins(
miacs[miacs$year==year,], "state", "mh_inc",
legend_title="States", legend_position="none",
brewer_pal="Greens", text_color="black", font_size=3,
plot_title=sprintf("Median Household Income (ACS) %d\n$%s - $%s", year,
scales::comma(rng[1]), scales::comma(rng[2])),
title_position="top"
) -> ggtmp
print(ggtmp)
dev.off()
fig
}) %>% image_join() %>%
image_animate(fps=2, loop=1)
```
<center>![img](./tmp/household.gif)</embed></center>
```{r}
library(statebins)
library(tidyverse)
library(viridis)
data(USArrests)
# make up some data for the example
rownames_to_column(USArrests, "state") %>%
bind_rows(
data_frame(
state = c("Virgin Islands", "Puerto Rico", "New York City"),
Murder = rep(mean(max(USArrests$Murder),3)),
Assault = rep(mean(max(USArrests$Assault),3)),
Rape = rep(mean(max(USArrests$Rape),3)),
UrbanPop = c(93, 95, 100)
)
) -> us_arrests
statebins(us_arrests, value_col="Assault",
ggplot2_scale_function = viridis::scale_fill_viridis) +
labs(title="USArrests + made up data") +
theme_statebins("right")
```

BIN
README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

BIN
README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

BIN
README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

BIN
README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

BIN
README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

BIN
README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

268
README.md

@ -7,22 +7,9 @@ Create ‘U.S.’ Uniform Square State Cartogram Heatmaps
The following functions are implemented:
- `statebins` - creates “statebin” charts in the style of
<http://bit.ly/statebins> - This version uses discrete
`RColorBrewer` scales, binned by the “breaks” parameter.
- `statebins_continuous` - creates “statebin” charts in the style of
<http://bit.ly/statebins> - This version uses a continuous scale
based on `RColorBrewer` scales (passing in a 6 element
`RColorBrewer` palette to `scale_fill_gradientn`).
- `statebins_manual` - creates “statebin” charts using manually
specified colors in a column
## TODO
- The current version is usable, but I think the plot margins and the
legends need work
- Apply algorithm to switch to light-on-dark depending on the
background tile color
- `statebins`: Creates “statebin” charts in the style of
<http://bit.ly/statebins>
- `theme_statebins`: Base statebins theme
## Installation
@ -50,216 +37,117 @@ packageVersion("statebins")
``` r
# the original wapo data
cols(
fipst = col_character(), stab = col_character(), state = col_character(), workers1994 = col_integer(), workers1995 = col_integer(), workers1996 = col_integer(), workers1997 = col_integer(), workers1998 = col_integer(), workers1999 = col_integer(), workers2000 = col_integer(), workers2001 = col_integer(), workers2002 = col_integer(), workers2003 = col_integer(), workers2004 = col_integer(), workers2005 = col_integer(), workers2006 = col_integer(), workers2007 = col_integer(), workers2008 = col_integer(), workers2009 = col_integer(), workers2010 = col_integer(), workers2011 = col_integer(), workers2012 = col_integer(), workers2013 = col_integer(),
share_cut1994 = col_double(), share_cut1995 = col_double(), share_cut1996 = col_double(), share_cut1997 = col_double(), share_cut1998 = col_double(), share_cut1999 = col_double(), share_cut2000 = col_double(), share_cut2001 = col_double(), share_cut2002 = col_double(), share_cut2003 = col_double(), share_cut2004 = col_double(), share_cut2005 = col_double(), share_cut2006 = col_double(), share_cut2007 = col_double(), share_cut2008 = col_double(), share_cut2009 = col_double(), share_cut2010 = col_double(), share_cut2011 = col_double(), share_cut2012 = col_double(), share_cut2013 = col_double(),
avgshare = col_double(), avgshare94_00 = col_double(), avgshare01_07 = col_double(), avgshare08_12 = col_double()
) -> wapo_cols
adat <- read_csv("http://www.washingtonpost.com/wp-srv/special/business/states-most-threatened-by-trade/states.csv?cache=1",
col_types = wapo_cols)
gg <- statebins(
adat, "state", "avgshare94_00",
breaks = 4,
labels = c("0-1", "1-2", "2-3", "3-4"),
legend_title = "Share of workforce with jobs lost or threatened by trade",
font_size = 3,
brewer_pal = "Blues",
text_color = "black",
plot_title = "1994-2000",
title_position = "bottom"
)
gg
adat <- suppressMessages(read_csv("http://www.washingtonpost.com/wp-srv/special/business/states-most-threatened-by-trade/states.csv?cache=1"))
mutate(
adat,
share = cut(avgshare94_00, breaks = 4, labels = c("0-1", "1-2", "2-3", "3-4"))
) %>%
statebins(
value_col = "share",
ggplot2_scale_function = scale_fill_brewer,
name = "Share of workforce with jobs lost or threatened by trade"
) +
labs(title = "1994-2000") +
theme_statebins()
```
<img src="README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-1.png" width="672" />
<img src="README_files/figure-gfm/unnamed-chunk-3-1.png" width="672" />
``` r
# continuous scale, legend on top
gg2 <- statebins_continuous(
adat, "state", "avgshare01_07",
legend_title="Share of workforce with jobs lost or threatened by trade", legend_position="top",
brewer_pal="OrRd", text_color="black", font_size=3,
plot_title="2001-2007", title_position="bottom"
)
gg2
statebins(
adat, value_col = "avgshare01_07",
name = "Share of workforce with jobs lost or threatened by trade",
palette = "OrRd", direction = 1
) +
labs(x="2001-2007") +
theme_statebins(legend_position="top")
```
<img src="README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-2.png" width="672" />
<img src="README_files/figure-gfm/unnamed-chunk-3-2.png" width="672" />
``` r
# continuous scale, no legend
gg3 <- statebins_continuous(
adat, "state", "avgshare08_12",
legend_title="States", legend_position="none",
brewer_pal="Purples", text_color="black", font_size=3,
plot_title="2008-2012", title_position="bottom"
)
gg3
statebins(adat, value_col = "avgshare08_12", palette = "Purples") +
labs(x="2008-2010") +
theme_statebins(legend_position = "none")
```
<img src="README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-3.png" width="672" />
<img src="README_files/figure-gfm/unnamed-chunk-3-3.png" width="672" />
``` r
# mortality (only to show PR and using a data.table)
# mortality data (has Puerto Rico)
# from: http://www.cdc.gov/nchs/fastats/state-and-territorial-data.htm
cols(
state = col_character(),
births = col_integer(),
fertility_rate = col_double(),
deaths = col_integer(),
death_rate = col_double()
) -> deaths_cols
dat <- read_csv("http://datadrivensecurity.info/data/deaths.csv", col_types=deaths_cols)
statebins_continuous(dat, "state", "death_rate", legend_title="Per 100K pop",
plot_title="Mortality Rate (2010)")
dat <- suppressMessages(read_csv("http://datadrivensecurity.info/data/deaths.csv"))
statebins(dat, value_col = "death_rate", name="Per 100K pop") +
labs(title="Mortality Rate (2010)") +
theme_statebins()
```
<img src="README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-4.png" width="672" />
<img src="README_files/figure-gfm/unnamed-chunk-3-4.png" width="672" />
``` r
# fertility (only to show tbl_dt)
# fertility data
statebins_continuous(dat, "state", "fertility_rate", legend_title="Per 100K pop",
plot_title="Fertility Rate (2010)", brewer_pal="PuBuGn")
statebins(dat, value_col="fertility_rate", name="Per 100K pop", palette="PuBuGn") +
labs(title="Fertility Rate (2010)") +
theme_statebins()
```
<img src="README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-5.png" width="672" />
<img src="README_files/figure-gfm/unnamed-chunk-3-5.png" width="672" />
``` r
# manual - perhaps good for elections?
library(httr)
library(dplyr)
election_2012 <- GET("https://raw.githubusercontent.com/hrbrmstr/statebins/master/tmp/election2012.csv")
read.csv(
textConnection(content(election_2012, as="text")),
header=TRUE, stringsAsFactors=FALSE
) %>%
mutate(color=ifelse(is.na(Obama), "#2166ac", "#b2182b")) %>%
select(state, color) -> results
statebins_manual(
results,
font_size=4, text_color = "white",
labels=c("Romney", "Obama"), legend_position="right", legend_title="Winner"
)
```
<img src="README.gfm-ascii_identifiers_files/figure-gfm/unnamed-chunk-3-6.png" width="672" />
``` r
# or, more like the one in the WaPo article; i might be picking the wrong columns here. it's just for an example
election_2012 <- suppressMessages(read_csv("https://raw.githubusercontent.com/hrbrmstr/statebins/master/tmp/election2012.csv"))
sb <- function(col, title) {
mutate(election_2012, value = ifelse(is.na(Obama), "Romney", "Obama")) %>%
statebins(
adat, "state", col, brewer_pal="Blues", text_color="black",
legend_position="none", font_size=3, plot_title=title,
breaks=4, labels=1:4
)
}
```
``` r
# cheating and using <table> to arrange them below and also making a WaPo-like legend,
# since mucking with grid graphics margins/padding was not an option time-wise at the moment
sb("avgshare94_00", "1994-2000")
sb("avgshare01_07", "2001-2007")
sb("avgshare08_12", "2008-2012")
font_size=4, dark_label = "white", light_label = "white",
ggplot2_scale_function = scale_fill_manual,
name = "Winner",
values = c(Romney = "#2166ac", Obama = "#b2182b")
) +
theme_statebins()
```
<!-- uncomment the following and add backticks where appropriate and remove the reference to -->
<img src="README_files/figure-gfm/unnamed-chunk-3-6.png" width="672" />
<!-- the static image when the rmarkdown output is HTML and this will work fine. github does not render the markdown properly -->
### All the “states”
<!--
<span style="font-size:17px; color:#333;">Share of workforce with jobs lost or threatened by trade</span><br/>
<table style="width:200px" cellpadding=0, cellspacing=0><tr style="line-height:10px">
<td width="25%" style="background:#EFF3FF;">&nbsp;</td>
<td width="25%" style="background:#BDD7E7;">&nbsp;</td>
<td width="25%" style="background:#6BAED6;">&nbsp;</td>
<td width="25%" style="background:#2171B5;">&nbsp;</td></tr>
<tr><td colspan=2 align="left" style="font-size:14px">Smallest share</td><td colspan=2 align="right" style="font-size:14px">Largest</td></tr>
</table>
<table width="100%" cellpadding="0" cellspacing="0">
<tr><td width="50%">
{r f1994, echo=FALSE, fig.width=6, fig.height=5}
sb("avgshare94_00", "1994-2000")
</td><td width="50%">
{r f2001, echo=FALSE, fig.width=6, fig.height=5, results='asis'}
sb("avgshare01_07", "2001-2007")
</td></tr><tr><td width="50%">
{r f2008, echo=FALSE, fig.width=6, fig.height=5, results='asis'}
sb("avgshare08_12", "2008-2012")
</td><td width="50%"> &nbsp; </td></tr></table>
-->
<center>
![img](./tmp/statebins-composite.png)
</center>
And, we’ll throw in a gratuitous animation for good measure:
`statebins` now has PR, VI & NYC (by name or abbreviation) so you can
use them, too:
``` r
library(magick)
# data set from StatsAmerica - http://www.statsamerica.org/profiles/sip_index.html
# median household income from the ACS survey
miacs <- read.csv("http://datadrivensecurity.info/data/median-income-acs.csv",
header=TRUE, stringsAsFactors=FALSE)
# generate frames based on year
purrr::map(unique(miacs$year), function(year) {
cat(".")
fig <- magick::image_graph(res=144)
rng <- floor(range(miacs[miacs$year==year,]$mh_inc))
statebins(
miacs[miacs$year==year,], "state", "mh_inc",
legend_title="States", legend_position="none",
brewer_pal="Greens", text_color="black", font_size=3,
plot_title=sprintf("Median Household Income (ACS) %d\n$%s - $%s", year,
scales::comma(rng[1]), scales::comma(rng[2])),
title_position="top"
) -> ggtmp
print(ggtmp)
dev.off()
fig
}) %>% image_join() %>%
image_animate(fps=2, loop=1)
library(statebins)
library(tidyverse)
library(viridis)
data(USArrests)
# make up some data for the example
rownames_to_column(USArrests, "state") %>%
bind_rows(
data_frame(
state = c("Virgin Islands", "Puerto Rico", "New York City"),
Murder = rep(mean(max(USArrests$Murder),3)),
Assault = rep(mean(max(USArrests$Assault),3)),
Rape = rep(mean(max(USArrests$Rape),3)),
UrbanPop = c(93, 95, 100)
)
) -> us_arrests
statebins(us_arrests, value_col="Assault",
ggplot2_scale_function = viridis::scale_fill_viridis) +
labs(title="USArrests + made up data") +
theme_statebins("right")
```
<center>
![img](./tmp/household.gif)</embed>
</center>
<img src="README_files/figure-gfm/unnamed-chunk-4-1.png" width="672" />

BIN
README_files/figure-gfm/unnamed-chunk-3-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
README_files/figure-gfm/unnamed-chunk-3-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
README_files/figure-gfm/unnamed-chunk-3-3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
README_files/figure-gfm/unnamed-chunk-3-4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
README_files/figure-gfm/unnamed-chunk-3-5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
README_files/figure-gfm/unnamed-chunk-3-6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
README_files/figure-gfm/unnamed-chunk-4-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

80
man/statebins.Rd

@ -2,14 +2,12 @@
% Please edit documentation in R/statebins.R
\name{statebins}
\alias{statebins}
\title{Create a new ggplot-based "statebin" chart for USA states (discrete scale)}
\title{Create a new ggplot-based "statebin" chart for USA states/territories}
\usage{
statebins(state_data, state_col = "state", value_col = "value",
text_color = "black", font_size = 3, state_border_col = "white",
breaks = 5, labels = 1:5, legend_title = "Legend",
legend_position = "top", palette = c("brewer", "viridis"),
viridis_pal = NULL, brewer_pal = "palette", plot_title = "",
title_position = "bottom")
dark_label = "black", light_label = "white", font_size = 3,
state_border_col = "white", state_border_size = 2,
ggplot2_scale_function = ggplot2::scale_fill_distiller, ...)
}
\arguments{
\item{state_data}{data frame of states and values to plot}
@ -19,70 +17,44 @@ and can be names (e.g. "\code{Maine}") or abbreviatons (e.g. "\code{ME}")}
\item{value_col}{column name in \code{state_data} that holds the values to be plotted}
\item{text_color}{default "\code{black}". Size 1 for global color across all tiles or
a vector of colors the same length as the number of states you passed in.
Use the sort order for the states as they are sorted before being plotted.}
\item{dark_label, light_label}{dark/light label colors. The specified color will be used
when the algorithm determines labels should be inverted.}
\item{font_size}{font size (default = \code{3})}
\item{state_border_col}{default "\code{white}" - this creates the "spaces" between boxes}
\item{breaks}{a single number (greater than or equal to 2) giving the number of intervals
into which data values are to be cut.}
\item{state_border_size}{border size}
\item{labels}{labels for the levels \code{breaks}}
\item{legend_title}{title for the legend}
\item{legend_position}{"\code{none}", "\code{top}", "\code{left}", "\code{right}" or
"\code{bottom}" (defaults to "\code{top}")}
\item{palette}{either "`brewer`" or "`viridis`". Choose `viridis` if you have
10 or more levels (more than 10 is not recommended). You can choose which
viridis palette option (e.g. "magma") with `viridis_pal`.}
\item{viridis_pal}{which named \code{viridis} palette option to use (default if `NULL`);
used when `palette` is `viridis`.}
\item{brewer_pal}{which named \code{RColorBrewer} palette to use (defaults to "PuBu");
used when `palette` is `brewer`.}
\item{plot_title}{title for the plot}
\item{title_position}{where to put the title ("\code{bottom}" or "\code{top}" or ""
for none); if "\code{bottom}", you get back a grob vs a ggplot object}
\item{ggplot2_scale_function}{ggplot2 scale function to use. Defaults to \code{scale_fill_distiller}
since you're likely passing in continuous data when you shouldn't be :-)}
}
\value{
ggplot2 object or grob
ggplot2 object
}
\description{
\code{statebins()} creates "statebin" charts in the style of \url{http://bit.ly/statebins}
Pass in a data frame and get back a square choropleth.
}
\details{
This version uses discrete \code{RColorBrewer} scales, binned by the "breaks" parameter.
The \code{state_col} and \code{value_col} parameters default to \code{state} and \code{value}. That means
if you name the columns you want to plot with those names, you can forego passing them
in. Othersise, use \code{"strings"}.
The function minimally expects the caller to pass in a data frame that:
A \emph{handy} feature of this function is that you can specify a \code{dark_label} color
and a \code{light_label} color. What does that mean? Well, you also pass in the
color scale function you're going to use and \code{statebins} will apply it and use
that information to determine what the tile color is and --- if it's "dark" it will
use the \code{light_label} and if it's "light" it will use the \code{dark_label} color. That
means the labels will never blend in to the background (as long as you specify
decent label colors).
\itemize{
\item has one column of all state abbreviationis (all caps, including \code{DC} &
\code{PR} or a column of state names (standard capitalization) named \code{state}
\item has another column of values named \code{value}
}
Doing so will create a "statebin" chart with 5 breaks and return a ggplot2 object.
You can use a different column for the state names and values by changing \code{state_col}
and \code{value_col} accordingly.
To add a title, change \code{plot_title} to anything but an empty atomic string vector (i.e. \code{""})
and set \code{title_position} to "\code{top}" or "\code{bottom}". Choosing "\code{bottom}"
will cause \code{statebins} to use the X axis title as the title.
You can customize the scale function you pass in by using name parameters. All named
parameters not used by \code{statebins()} itself get passed to the scale function.
}
\examples{
\dontrun{
data(USArrests)
USArrests$state <- rownames(USArrests)
statebins(USArrests, value_col="Assault", text_color="black", font_size=3,
legend_title = "Assault", legend_position="bottom")
}
statebins(USArrests, value_col="Assault", name = "Assault") +
theme_statebins(legend_position="right")
}

74
man/statebins_continuous.Rd

@ -1,74 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/statebins-continuous.R
\name{statebins_continuous}
\alias{statebins_continuous}
\title{Create a new ggplot-based "statebin" chart for USA states (continuous scale)}
\usage{
statebins_continuous(state_data, state_col = "state", value_col = "value",
text_color = "black", font_size = 3, state_border_col = "white",
legend_title = "Legend", legend_position = "top", brewer_pal = "PuBu",
plot_title = "", title_position = "bottom")
}
\arguments{
\item{state_data}{data frame of states and values to plot}
\item{state_col}{column name in \code{state_data} that has the states. no duplicates
and can be names (e.g. "\code{Maine}") or abbreviatons (e.g. "\code{ME}")}
\item{value_col}{column name in \code{state_data} that holds the values to be plotted}
\item{text_color}{default "\code{black}". Size 1 for global color across all tiles or
a vector of colors the same length as the number of states you passed in.
Use the sort order for the states as they are sorted before being plotted.}
\item{font_size}{font size (default = \code{3})}
\item{state_border_col}{default "\code{white}" - this creates the "spaces" between boxes}
\item{legend_title}{title for the legend}
\item{legend_position}{"\code{none}", "\code{top}", "\code{left}", "\code{right}" or
"\code{bottom}" (defaults to "\code{top}")}
\item{brewer_pal}{which named \code{RColorBrewer} palette to use (defaults to "PuBu")}
\item{plot_title}{title for the plot}
\item{title_position}{where to put the title ("\code{bottom}" or "\code{top}" or ""
for none); if "\code{bottom}", you get back a grob vs a ggplot object}
}
\value{
ggplot2 object or grob
}
\description{
\code{statebins()} creates "statebin" charts in the style of \url{http://bit.ly/statebins}
}
\details{
This version uses a continuous scale based on \code{RColorBrewer} scales
(passing in a 6 element \code{RColorBrewer} palette to \code{scale_fill_gradientn}).
The function minimally expects the caller to pass in a data frame that:
\itemize{
\item has one column of all state abbreviationis (all caps, including \code{DC} &
\code{PR} ) or a column of state names (standard capitalization) named \code{state}
\item has another column of values named \code{value}
}
Doing so will create a "statebin" chart with 5 breaks and return a \code{ggplot2} object.
You can use a different column for the state names and values by changing \code{state_col}
and \code{value_col} accordingly.
To add a title, change \code{plot_title} to anything but an empty atomic string vector (i.e. \code{""})
and set \code{title_position} to "\code{top}" or "\code{bottom}". Choosing "\code{bottom}"
will cause \code{statebins} to use the X axis title placeholder.
}
\examples{
\dontrun{
data(USArrests)
USArrests$state <- rownames(USArrests)
statebins_continuous(USArrests, value_col="Murder", text_color="black", font_size=3,
legend_title = "Murder", legend_position="bottom")
}
}

83
man/statebins_manual.Rd

@ -1,83 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/statebins-manual.R
\name{statebins_manual}
\alias{statebins_manual}
\title{Create a new ggplot-based "statebin" chart for USA states (manually colored)}
\usage{
statebins_manual(state_data, state_col = "state", color_col = "color",
text_color = "black", font_size = 3, state_border_col = "white",
labels = NULL, legend_title = "Legend", legend_position = "top",
plot_title = "", title_position = "bottom")
}
\arguments{
\item{state_data}{data frame of states and values to plot}
\item{state_col}{column name in \code{state_data} that has the states. no duplicates
and can be names (e.g. "\code{Maine}") or abbreviatons (e.g. "\code{ME}")}
\item{color_col}{column name in \code{state_data} that holds the colors to be used}
\item{text_color}{default "\code{black}". Size 1 for global color across all tiles or
a vector of colors the same length as the number of states you passed in.
Use the sort order for the states as they are sorted before being plotted.}
\item{font_size}{font size (default = \code{3})}
\item{state_border_col}{default "\code{white}" - this creates the "spaces" between boxes}
\item{labels}{labels for the legend (should be the same number as distinct colors in
\code{color_col}); \code{NULL} == no labels/legend}
\item{legend_title}{title for the legend}
\item{legend_position}{"\code{none}", "\code{top}", "\code{left}", "\code{right}" or
"\code{bottom}" (defaults to "\code{top}")}
\item{plot_title}{title for the plot}
\item{title_position}{where to put the title ("\code{bottom}" or "\code{top}" or ""
for none); if "\code{bottom}", you get back a grob vs a ggplot object}
}
\value{
ggplot2 object or grob
}
\description{
\code{statebins()} creates "statebin" charts in the style of \url{http://bit.ly/statebins}
}
\details{
This version uses manual colors (i.e. pass in a column that defines the color per-state)
The function minimally expects the caller to pass in a data frame that:
\itemize{
\item has one column of all state abbreviationis (all caps, including \code{DC} &
\code{PR} or a column of state names (standard capitalization) named \code{state}
\item has another column of colors named \code{color}
}
Doing so will create a "statebin" chart with the colors specified as a ggplot2 object.
You can use a different column for the state names and colors by changing \code{state_col}
and \code{color_col} accordingly.
To add a title, change \code{plot_title} to anything but an empty atomic string vector (i.e. \code{""})
and set \code{title_position} to "\code{top}" or "\code{bottom}". Choosing "\code{bottom}"
will cause \code{statebins} to use the X axis title placeholder.
}
\examples{
\dontrun{
library(httr)
library(dplyr)
election_2012 <-
GET("https://raw.githubusercontent.com/hrbrmstr/statebins/master/tmp/election2012.csv")
results <- read.csv(textConnection(content(election_2012, as="text")),
header=TRUE, stringsAsFactors=FALSE)
results <- results \%>\%
mutate(color=ifelse(is.na(Obama), "#2166ac", "#b2182b")) \%>\%
select(state, color)
results \%>\%
statebins_manual(font_size=4,
text_color = "white", labels=c("Romney", "Obama"),
legend_position="right", legend_title="Winner")
}
}

18
man/theme_statebins.Rd

@ -0,0 +1,18 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/theme-statebin.R
\name{theme_statebins}
\alias{theme_statebins}
\title{Base statebins theme}
\usage{
theme_statebins(legend_position = "bottom", base_size = 11,
base_family = "", base_line_size = base_size/22,
base_rect_size = base_size/22)
}
\arguments{
\item{legend_position}{fills in \code{legend.position}}
\item{base_family, base_size, base_line_size, base_rect_size}{same as \code{theme_bw()}}
}
\description{
Clears out most of the cruft. Builds off of \code{theme_bw()}
}

52
tmp/election2012.csv

@ -1,52 +0,0 @@
state,Obama,Romney
AL,,9
AK,,3
AZ,,11
AR,,6
CA,55,
CO,9,
CT,7,
DE,3,
DC,3,
FL,29,
GA,,16
HI,4,
ID,,4
IL,20,
IN,,11
IA,6,
KS,,6
KY,,8
LA,,8
ME,4,
MD,10,
MA,11,
MI,16,
MN,10,
MS,,6
MO,,10
MT,,3
NE,,5
NV,6,
NH,4,
NJ,14,
NM,5,
NY,29,
NC,,15
ND,,3
OH,18,
OK,,7
OR,7,
PA,20,
RI,4,
SC,,9
SD,,3
TN,,11
TX,,38
UT,,6
VT,3,
VA,13,
WA,12,
WV,,5
WI,10,
WY,,3
1 state Obama Romney
2 AL 9
3 AK 3
4 AZ 11
5 AR 6
6 CA 55
7 CO 9
8 CT 7
9 DE 3
10 DC 3
11 FL 29
12 GA 16
13 HI 4
14 ID 4
15 IL 20
16 IN 11
17 IA 6
18 KS 6
19 KY 8
20 LA 8
21 ME 4
22 MD 10
23 MA 11
24 MI 16
25 MN 10
26 MS 6
27 MO 10
28 MT 3
29 NE 5
30 NV 6
31 NH 4
32 NJ 14
33 NM 5
34 NY 29
35 NC 15
36 ND 3
37 OH 18
38 OK 7
39 OR 7
40 PA 20
41 RI 4
42 SC 9
43 SD 3
44 TN 11
45 TX 38
46 UT 6
47 VT 3
48 VA 13
49 WA 12
50 WV 5
51 WI 10
52 WY 3

BIN
tmp/household.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

BIN
tmp/household2000.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

BIN
tmp/household2001.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

BIN
tmp/household2002.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

BIN
tmp/household2003.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

BIN
tmp/household2004.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

BIN
tmp/household2005.png