Last active
August 29, 2015 14:17
-
-
Save rich-iannone/a4f44f6fcaece76d4e41 to your computer and use it in GitHub Desktop.
This is a Graphviz diagram that shows major US cities (with population greater than 300,000 people). Uses chromatography.js to provide some color by US state, and, the DiagrammeR R package (https://github.com/rich-iannone/DiagrammeR) to render the graph.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# install.packages("downloader") | |
# devtools::install_github("rich-iannone/DiagrammeR") | |
# devtools::install_github("jeroenooms/V8") | |
library("downloader") | |
library("DiagrammeR") | |
library("V8") | |
# Create a function that uses the 'chromatography' JS library to generate a random | |
# set of colors from the CIE Lab color space | |
hex_palette <- function(no_colors, | |
hue_range = NULL, | |
chroma_range = NULL, | |
lightness_range = NULL, | |
display_colors = TRUE){ | |
# Construct the JS call | |
js_call <- paste0("var colors = createPalette.generate(", | |
no_colors, ", function(color){ var hcl = color.hcl(); return hcl[0]>=", | |
hue_range[1], " && hcl[0]<=", | |
hue_range[2], "&& hcl[1]>=", | |
chroma_range[1], "&& hcl[1]<=", | |
chroma_range[2], "&& hcl[2]>=", | |
lightness_range[1], "&& hcl[2]<=", | |
lightness_range[2], "; }, true, 50);", | |
"var colors = createPalette.diffSort(colors); colors;") | |
# Add function to display colors in the RStudio Viewer | |
display_in_viewer <- function(col, border = "light gray", ...){ | |
n <- length(col) | |
plot(0, 0, type = "n", xlim = c(0, 1), ylim = c(0, 1), | |
axes = FALSE, xlab = "", ylab = "", ...) | |
rect(0:(n-1)/n, 0, 1:n/n, 1, col = col, border = border) | |
} | |
ct <- new_context("window") | |
invisible(ct$source(system.file("htmlwidgets/lib/chromatography/chromatography.js", | |
package = "DiagrammeR"))) | |
hex_colors <- unlist(strsplit(ct$eval(js_call), ",")) | |
if (display_colors == TRUE){ | |
display_in_viewer(hex_colors) | |
} | |
return(hex_colors) | |
} | |
# Download a CSV file containing information on US cities (e.g., names, states, population, | |
# lonlat coordinates); uses the 'download' function from the 'downloader' package | |
tmpfile <- tempfile() | |
download("https://raw.githubusercontent.com/rich-iannone/DiagrammeR/master/inst/examples/us_cities.csv", | |
tmpfile, mode = "wb") | |
# Create the 'us_cities' data frame object using the CSV file | |
us_cities <- read.csv(tmpfile, header = TRUE, stringsAsFactors = FALSE) | |
# Subset the data frame so that only cities with populations greater than | |
# 300,000 people remain | |
population_us_cities <- us_cities[us_cities[,5] > 300000,] | |
# Subset the data frame by a latitude and longitude bounding box so that only the | |
# lower 48 states are included (column 6 is latitude, 7 is longitude) | |
population_us_cities_lower48 <- | |
population_us_cities[population_us_cities[,6] < 49.384358,] | |
population_us_cities_lower48 <- | |
population_us_cities_lower48[population_us_cities_lower48[,6] > 24.396308,] | |
population_us_cities_lower48 <- | |
population_us_cities[population_us_cities[,7] < -66.885444,] | |
population_us_cities_lower48 <- | |
population_us_cities_lower48[population_us_cities_lower48[,7] > -124.848974,] | |
# Get a vector of the states available in the dataframe | |
us_states <- | |
unique(population_us_cities_lower48[,4]) | |
# Define a number of distinct, yet light, colors for coloring nodes for each state | |
us_state_colors <- hex_palette(no_colors = length(us_states), | |
hue_range = c(0, 360), | |
chroma_range = c(0, 3), | |
lightness_range = c(0.75, 1.5)) | |
# Create a block of node statements for subsitution into the Graphviz DOT statement | |
for (i in 1:length(us_states)){ | |
if (i == 1) us_cities_nodes <- vector(mode = "character", length = 0) | |
# Create the node block element for each statement (includes an informative tooltip) | |
us_state_cities_nodes <- | |
paste("'", | |
population_us_cities[population_us_cities[,4] == us_states[i], 3], | |
"' [fillcolor = '", | |
us_state_colors[i], | |
"', tooltip = '", | |
population_us_cities[population_us_cities[,4] == us_states[i], 3], "\n", | |
"pop: ", prettyNum(population_us_cities[population_us_cities[,4] == us_states[i], 5], | |
big.mark = ",", scientific = FALSE), | |
"' pos = '", | |
population_us_cities[population_us_cities[,4] == us_states[i], 7], ",", | |
population_us_cities[population_us_cities[,4] == us_states[i], 6], "!']", | |
sep = "", collapse = "\n") | |
us_cities_nodes <- c(us_cities_nodes, us_state_cities_nodes) | |
if (i == length(us_states)){ | |
us_cities_nodes <- paste(us_cities_nodes, collapse = "\n") | |
} | |
} | |
# Create a block of edge statements for subsitution into the Graphviz DOT statement | |
for (i in 1:length(us_states)){ | |
if (i == 1) us_cities_edges <- vector(mode = "character", length = 0) | |
# Create the edge block element for each statement | |
us_state_cities_edges <- | |
paste("'", | |
population_us_cities[i,3], "'--'", population_us_cities[-i, 3], | |
"'", | |
sep = "", collapse = "\n") | |
us_cities_edges <- c(us_cities_edges, us_state_cities_edges) | |
if (i == length(us_states)){ | |
us_cities_edges <- paste(us_cities_edges, collapse = "\n") | |
} | |
} | |
# Create the graph diagram, showing major US cities with populations greater than | |
# 300,000 people. Colored by state, using coordinate information to position nodes on | |
# the graph canvas | |
grViz(" | |
graph USA { | |
graph [layout = neato, | |
overlap = true, | |
outputorder = edgesfirst] | |
# US cities | |
node [shape = circle, style = filled, height = 1, label = ''] | |
@@1 | |
# Connections between cities | |
edge [color = '#5B8FA550'] | |
@@2 | |
} | |
[1]: us_cities_nodes | |
[2]: us_cities_edges | |
") | |
# After creating the graph in the RStudio Viewer, hover over city | |
# nodes to get city names and population data | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment