sankeytreeR is very experimental and a little fragile, but it will give us a good testbed for this discussion. This little bit of code requires dplyr, tibble, treemap, sankeytreeR, shiny, d3r. All are on CRAN except for sankeytreeR.
#devtools::install_github("timelyportfolio/sankeytree")
library(d3r)
library(sankeytreeR)
library(shiny)
library(treemap)sankeytree’s fragility requires a little prep work to prep the data. We can use treemap::random.hierarchical.data with d3r for the nested JSON and treemap for the summing over nodes/levels to generate the data in proper form for sankeytree. Most of this portion of the code can be ignored for the purposes of discussion.
rhd <- random.hierarchical.data(depth=2)
tm <- treemap(
rhd,
vSize="x",
index=c("index1","index2")
)$tm
rhd_d3 <- d3_nest(
tm,
value_cols = colnames(tm)[-c(1:2)],
json = FALSE
)
rhd_d3$vSize = sum(rhd$x)
rhd_json <- d3_json(rhd_d3)We can now plot rhd_json as a sankeytree.
st <- sankeytree(rhd_json, name="id", value="vSize")
st$elementId <- "sankeytree"
st# add a update handler on sankeytree
ui <- htmlwidgets::onRender(
st,
htmlwidgets::JS(
'
function(el,x) {
this.on("update", function(x){
console.log(x);
// here we could have it return as much
// information as we would like
Shiny.onInputChange(
el.id + "_update",
{
nodes:d3.layout.tree().nodes(x.root).map(function(node){
var flatnode = {};
Object.keys(node).map(function(key){
if(["children","_children","parent"].indexOf(key)<0){
flatnode[key] = node[key];
}
});
return flatnode;
})
}
);
});
}
'
)
)
server <- function(input, output, session) {
observeEvent(input$sankeytree_update, {
print(
dplyr::bind_rows(
lapply(input$sankeytree_update$nodes,tibble::as_tibble)
)
)
})
}
# turn on trace logging of shiny websocket messages
#options(shiny.trace=TRUE)
shinyApp(ui,server)