Skip to content

Instantly share code, notes, and snippets.

@rich-iannone
Last active August 29, 2015 14:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rich-iannone/a4f44f6fcaece76d4e41 to your computer and use it in GitHub Desktop.
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.
# 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