Introduction

I have begun using a Sankey diagram to illustrate various types of connections among my projects. Here the purpose is to show the code used to create the project hierarchy graph shows elsewhere (and below).

Motivation

I have created this diagram showing project and collaborator relationships that occur in my current work as part of this rpm Project Management Project. However, this is a special case shown here. In general, the reason for folding this type of graph into all of my individual projects as part of project management is to show code and data relationships that exist for a specific project. For example, rpm has its own code flow diagram as do my other projects. But here the focus is on the particular project hierarchy diagram that is part of this project.

Project hierarchy R code

Here is the code used to generate the current project hierarchy diagram. Two packages are required.

require(igraph)
require(rCharts)

Current projects are hardcoded and are updated by hand when my work changes. A necessary evil. This is essentially the data, consisting of both projects and collaborators.

proj.mp <- c("Alfresco Noatak", "Alfresco Statewide", "Spatial Lightning Analysis", 
    "Data Extraction and Uncertainty Analysis", "Growing Season", "Mussel Project", 
    "Land Carbon")
proj.etal <- c("Alfresco CRU/GCM Experimental Design", "Bird Project", "NWT/Comm. Charts DS", 
    "Sea Ice Edge Maps and Spinoff Projects", "Shiny App Server Migration")
proj.m <- c("CMIP3/CMIP5 GCM Comparisons", "Effective Spatial Scale Analysis", 
    "Randscape Development", "Alfresco Outputs", "rpm")
proj.ongoing <- c("SNAP Data QA/QC", "Training/Supervision", "R Shiny Apps General Maintenance", 
    "New App Development", "SNAP Tech Blog", "Continuing Education")
proj.halted <- c("FRP/FRI Scale-Conditional Alfresco Maps", "Moose Project")
projects.list <- list(proj.mp, proj.etal, proj.m, proj.ongoing, proj.halted)
actors.etal <- list(c("Paul", "Alec"), "Angie", c("Angie", "Bob"), "Angie", 
    "Bob")
actors.all <- unique(c("Matt", "Paul", unlist(actors.etal)))

Directional connections must be made among project and among people and projects. The connections are expressed by element-wise comparison of the equal-length to and from vectors.

from <- c(
    # LHS
    rep("Collaborators", length(actors.all[actors.all!="Matt"])),
    rep("Matt", length(c(proj.m, proj.ongoing, proj.halted))),
    rep(c("Matt", "Paul"), length(proj.mp)),
    rep("Matt", length(proj.etal)),
    unlist(actors.etal),
    # Specific connections
    rep("Alfresco Outputs", 3),
    rep("SNAP Data QA/QC", 4),
    rep("Spatial Lightning Analysis", 3),
    rep("Sea Ice Edge Maps and Spinoff Projects", 2),
    rep("Training/Supervision", 2),
    rep("Randscape Development", 2),
    rep("Effective Spatial Scale Analysis", 2),
    rep("NWT/Comm. Charts DS", 1),
    c("Alfresco Noatak", "Alfresco Statewide"),
    rep("Data Extraction and Uncertainty Analysis", 4)
)

to <- c(
    actors.all[actors.all!="Matt"],
    proj.m,
    proj.ongoing,
    proj.halted,
    rep(proj.mp, 2),
    proj.etal,
    rep(proj.etal, times=sapply(actors.etal, length)),
    # Specific connections
    c("CMIP3/CMIP5 GCM Comparisons", "Land Carbon", "Bird Project"), # from "Alfresco Outputs"
    c("Alfresco Outputs", "CMIP3/CMIP5 GCM Comparisons", "Alfresco CRU/GCM Experimental Design", "NWT/Comm. Charts DS"), # from "SNAP Data QA/QC"
    c("Alfresco Noatak", "Alfresco Statewide", "Randscape Development"), # from "Spatial Lightning Analysis
    c("Randscape Development", "Alfresco Outputs"), # from "Sea Ice Edge Maps and Spinoff Projects"
    c("Bird Project", "NWT/Comm. Charts DS"), # from "Training/Supervision"
    c("Alfresco Outputs", "Effective Spatial Scale Analysis"), # from "Randscape Development
    c("Alfresco Outputs", "FRP/FRI Scale-Conditional Alfresco Maps"), # from "Effective Spatial Scale Analysis"
    c("CMIP3/CMIP5 GCM Comparisons"), #from "NWT/Comm. Charts DS"
    rep("FRP/FRI Scale-Conditional Alfresco Maps", 2), # from "Alfresco Noatak", "Alfresco Statewide"
    c("CMIP3/CMIP5 GCM Comparisons", "Effective Spatial Scale Analysis", "Randscape Development", "Alfresco Outputs") # from "Data Extraction and Uncertainty Analysis"
)

The vectors are combined in a data frame and the igraph package is used to grow the tree diagram.

relations <- data.frame(from = from, to = to)
g <- graph.data.frame(relations, directed = T, vertices = data.frame(c("Collaborators", 
    actors.all, unlist(projects.list))))

gw <- get.data.frame(g)
gw$value <- 1
colnames(gw) <- c("source", "target", "value")
gw$source <- as.character(gw$source)
gw$target <- as.character(gw$target)

The rcharts package has functionality for turning this into an interactive D3 visualization, which is nice, particularly the mouseover interactivity, since there can be so much visual overlap among projects. Additional javascript can be included to alter the colors. My strengths are in R so I borrowed this code snippet from online, but if you have skills with javascript and D3 you could probably do better with color control and opacity I imagine.

p <- rCharts$new()
p$setLib("http://timelyportfolio.github.io/rCharts_d3_sankey/libraries/widgets/d3_sankey")
p$setTemplate(script = "http://timelyportfolio.github.io/rCharts_d3_sankey/libraries/widgets/d3_sankey/layouts/chart.html")
p$set(data = gw, nodeWidth = 15, nodePadding = 10, layout = 32, width = 900, 
    height = 800, margin = list(right = 20, left = 20, bottom = 20, top = 20), 
    title = "Matt's Projects")

p$setTemplate(afterScript = "\n<script>\n  var cscale = d3.scale.category20b();\n  d3.selectAll('#{{ chartId }} svg path.link')\n    .style('stroke', function(d){\n      return cscale(d.source.name);\n    })\n  d3.selectAll('#{{ chartId }} svg .node rect')\n    .style('fill', function(d){\n      return cscale(d.name)\n    })\n    .style('stroke', 'none')\n</script>\n")

Embed the chart in a document when rendering.

p$show("iframesrc", cdn=T)