@ -1,29 +1,27 @@ |
|||
Package: statebins |
|||
Type: Package |
|||
Title: U.S. State Cartogram Heatmaps in R; an Alternative to |
|||
Choropleth Maps for USA States |
|||
Version: 1.2.2 |
|||
Date: 2015-12-21 |
|||
Author: Bob Rudis (@hrbrmstr) |
|||
Maintainer: Bob Rudis <bob@rudis.net> |
|||
Description: Cartogram heatmaps are an alternative to choropleth maps for USA States |
|||
and are based on work by the Washington Post graphics department in their report |
|||
on "The states most threatened by trade". "State bins" preserve as much of the |
|||
geographic placement of the states as possible but has the look and feel of a |
|||
traditional heatmap. Functions are provided that allow for use of a binned, |
|||
discrete scale, a continuous scale or manually specified colors depending on |
|||
what is needed for the underlying data. |
|||
URL: http://github.com/hrbrmstr/statebins |
|||
Title: Create 'U.S.' Uniform Square State Cartogram Heatmaps |
|||
Version: 1.3.0 |
|||
Date: 2018-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 |
|||
and are based on work by the 'Washington Post' graphics department in their report |
|||
on "The states most threatened by trade" |
|||
<http://www.washingtonpost.com/wp-srv/special/business/states-most-threatened-by-trade/>. |
|||
"State bins" preserve as much of the geographic placement of the states as |
|||
possible but has the look and feel of a traditional heatmap. Functions are |
|||
provided that allow for use of a binned, discrete scale, a continuous scale |
|||
or manually specified colors depending on what is needed for the underlying data. |
|||
URL: https://github.com/hrbrmstr/statebins |
|||
BugReports: https://github.com/hrbrmstr/statebins/issues |
|||
License: MIT + file LICENSE |
|||
Suggests: |
|||
testthat |
|||
Depends: |
|||
R (>= 3.0.0), |
|||
R (>= 3.2.0), |
|||
Imports: |
|||
ggplot2, |
|||
grid, |
|||
gridExtra, |
|||
scales, |
|||
RColorBrewer |
|||
RoxygenNote: 5.0.1 |
|||
ggplot2 (>= 2.2.0), |
|||
scales (>= 0.5.0), |
|||
RColorBrewer (>= 1.1-2) |
|||
RoxygenNote: 6.0.1 |
|||
|
@ -0,0 +1,20 @@ |
|||
# statebins 1.3.0 |
|||
* Added support for `VI`/`Virgin Islands` |
|||
|
|||
# statebins 1.2.2 |
|||
* CRAN update |
|||
|
|||
# statebins 1.2.1 |
|||
* Added support for `PR`/`Puerto Rico`[[1](https://github.com/hrbrmstr/statebins/issues/2)] |
|||
and fixed a bug (#3) when using anything but a `data.frame` as input. Also no longer fails |
|||
(deals with the following but with a warning) when duplicate states are in the input data |
|||
or invalid states are in the input data. |
|||
|
|||
# statebins 1.1.0 |
|||
* `statebins_manual()` for manual placement of colors and moving of AK in support of a |
|||
(PR #1 by @hansthompson) |
|||
|
|||
# statebins 1.0.0 |
|||
* initial release |
|||
|
|||
|
@ -0,0 +1,27 @@ |
|||
state_coords <- structure(list(abbrev = c("AL", "AK", "AZ", "AR", "CA", "CO", |
|||
"CT", "DC", "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", |
|||
"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"), |
|||
state = c("Alabama", "Alaska", "Arizona", "Arkansas", |
|||
"California", "Colorado", "Connecticut", "District of Columbia", |
|||
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", |
|||
"Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", |
|||
"Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", |
|||
"Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", |
|||
"New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", |
|||
"Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", |
|||
"South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", |
|||
"Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming", |
|||
"Puerto Rico", "Virgin Islands"), |
|||
col = c(8L, 1L, 3L, 6L, 2L, 4L, 11L, 10L, 11L, 10L, |
|||
9L, 1L, 3L, 7L, 7L, 6L, 5L, 7L, 6L, 12L, 10L, 11L, 8L, 6L, 7L, |
|||
6L, 4L, 5L, 3L, 12L, 10L, 4L, 10L, 8L, 5L, 8L, 5L, 2L, 9L, 12L, |
|||
9L, 5L, 7L, 5L, 3L, 11L, 9L, 2L, 8L, 7L, 4L, 12L, 0L), |
|||
row = c(7L, 7L, |
|||
6L, 6L, 5L, 5L, 4L, 6L, 5L, 8L, 7L, 8L, 3L, 3L, 4L, 4L, 6L, 5L, |
|||
7L, 1L, 5L, 3L, 3L, 3L, 7L, 5L, 3L, 5L, 4L, 2L, 4L, 6L, 3L, 6L, |
|||
3L, 4L, 7L, 4L, 4L, 4L, 6L, 4L, 6L, 8L, 5L, 2L, 5L, 3L, 5L, 2L, 4L, 8L, 6L)), |
|||
.Names = c("abbrev", "state", "col", "row"), class = "data.frame", row.names = c(NA, -53L)) |
|||
|
@ -0,0 +1,105 @@ |
|||
#' 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 \code{arrangeGrob} to position the title via \code{sub} and |
|||
#' return a frame grob instead of a ggplot2 object. |
|||
#' |
|||
#' @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}" |
|||
#' @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) |
|||
|
|||
} |
@ -0,0 +1,116 @@ |
|||
#' 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 \code{arrangeGrob} to position the title via \code{sub} and |
|||
#' return a frame grob instead of a ggplot2 object. |
|||
#' |
|||
#' @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}" |
|||
#' @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")) |
|||
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) |
|||
|
|||
} |
@ -1,16 +1,15 @@ |
|||
#' statebins is an alternative to choropleth maps for US States |
|||
#' |
|||
#' @md |
|||
#' @name statebins-package |
|||
#' @docType package |
|||
#' @author Bob Rudis (@@hrbrmstr) |
|||
#' @import gridExtra RColorBrewer |
|||
#' @author Bob Rudis (bob@@rud.is) |
|||
#' @import RColorBrewer |
|||
#' @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 scale_fill_brewer ggtitle |
|||
#' @importFrom grid arrow unit grid.newpage grid.draw unit.c unit.pmax unit.pmin |
|||
#' @importFrom grid textGrob gpar |
|||
#' @importFrom ggplot2 scale_fill_brewer ggtitle rel |
|||
NULL |
|||
|
@ -0,0 +1,33 @@ |
|||
invert <- function(hexColor, darkColor="black", lightColor="white") { |
|||
|
|||
hexColor <- gsub("#", "", hexColor) |
|||
|
|||
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="")) |
|||
|
|||
YIQ <- ((R*299) + (G*587) + (B*114)) / 1000 |
|||
|
|||
return(ifelse(YIQ >= 128, darkColor, lightColor)) |
|||
|
|||
} |
|||
|
|||
# sanity checks for state values |
|||
validate_states <- function(state_data, state_col, merge.x) { |
|||
|
|||
good_states <- state_data[,state_col] %in% state_coords[,merge.x] |
|||
if (any(!good_states)) { |
|||
invalid <- state_data[,state_col][which(!good_states)] |
|||
state_data <- state_data[which(good_states),] |
|||
warning("Found invalid state values: ", invalid) |
|||
} |
|||
|
|||
dups <- duplicated(state_data[,state_col]) |
|||
if (any(dups)) { |
|||
state_data <- state_data[which(!dups),] |
|||
warning("Removing duplicate state rows") |
|||
} |
|||
|
|||
return(state_data) |
|||
|
|||
} |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 378 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |