Adding Color to Sankey Diagram in rCharts - r

I've created a sankey diagram in rCharts but have one question. How do I add color? I'd like to represent each node with a different color so it's easier to vizualize the paths, instead of just seeing the same grey lines connecting everything. Code and output below:
require(rCharts)
require(rjson)
x = read.csv('/Users/<username>/sankey.csv', header=FALSE)
colnames(x) <- c("source", "target", "value")
sankeyPlot <- rCharts$new()
sankeyPlot$set(
data = x,
nodeWidth = 15,
nodePadding = 10,
layout = 32,
width = 500,
height = 300,
units = "TWh",
title = "Sankey Diagram"
)
sankeyPlot$setLib('http://timelyportfolio.github.io/rCharts_d3_sankey')
sankeyPlot
Here is what my chart looks like
Thanks so much!

not sure what colors you want, but if you have installed the newer rCharts with devtools::install_github("ramnathv/rCharts"), here is how you might color based on the source value with a demo here.
require(rCharts)
require(rjson)
x = read.csv('/Users/<username>/sankey.csv', header=FALSE)
colnames(x) <- c("source", "target", "value")
sankeyPlot <- rCharts$new()
sankeyPlot$set(
data = x,
nodeWidth = 15,
nodePadding = 10,
layout = 32,
width = 500,
height = 300,
units = "TWh",
title = "Sankey Diagram"
)
sankeyPlot$setLib('http://timelyportfolio.github.io/rCharts_d3_sankey')
sankeyPlot$setTemplate(
afterScript = "
<script>
// to be specific in case you have more than one chart
d3.selectAll('#{{ chartId }} svg path.link')
.style('stroke', function(d){
//here we will use the source color
//if you want target then sub target for source
//or if you want something other than gray
//supply a constant
//or use a categorical scale or gradient
return d.source.color;
})
//note no changes were made to opacity
//to do uncomment below but will affect mouseover
//so will need to define mouseover and mouseout
//happy to show how to do this also
// .style('stroke-opacity', .7)
</script>
")
sankeyPlot
If you wanted to use a d3.scale.category??() to provide your color, I assume you would want to also similarly color the node rectangle. Here is one example of changing the color for both the node and the link.
sankeyPlot$setTemplate(
afterScript = "
<script>
var cscale = d3.scale.category20b();
// to be specific in case you have more than one chart
d3.selectAll('#{{ chartId }} svg path.link')
.style('stroke', function(d){
//here we will use the source color
//if you want target then sub target for source
//or if you want something other than gray
//supply a constant
//or use a categorical scale or gradient
//return d.source.color;
return cscale(d.source.name);
})
//note no changes were made to opacity
//to do uncomment below but will affect mouseover
//so will need to define mouseover and mouseout
//happy to show how to do this also
// .style('stroke-opacity', .7)
d3.selectAll('#{{ chartId }} svg .node rect')
.style('fill', function(d){
return cscale(d.name)
})
.style('stroke', 'none')
</script>
")
sankeyPlot

Related

Preserve custom node placement of a sankeyNetwork (networkD3) in R

I wish to customise the horizontal and vertical position of nodes in a sankeyNetwork (networkD3) in R, and export the network as a high-resolution image.
I credit and use the reproducible example of CJ Yetman (enable horizontal movement of nodes in networkD3's sankeyNetwork plots) which allows the user to move the nodes in any horizontal and vertical position:
library(networkD3)
library(htmlwidgets)
ID <- 0:24
NodeGroup <- c(rep(1,8),2,5,rep(4,7),3,5,6,6,7,7,8,9)
name <- c("29581k","5279k","4218k","1917k","1356k","Ventas diversas: 116",
"Venta diversa: 97","Venta de: 141","Venta totales: 42705",
"Contribucion marginal: 18183", "17531k","1744k","1326k","1208k",
"526k","459k","14k","IIBB: 1714","Costo: 22808",
"Gastos directos: 6734", "Gastos distribudos: 2958","Resultado: 8851",
"Total Gastos: 9332","Imp. Gcias: 3098","Resultado Netto: 5.753")
nodes <- data.frame(ID, name, NodeGroup)
nodes$NodeGroup <- as.character(nodes$NodeGroup)
source <- c(0:7, rep(8,9), 10:16, rep(9,3), 19, 20, 21, 21)
target <- c(rep(8,8), 17, 10:16, 9, rep(18,7), 19:21, rep(22, 2), 23, 24)
value <- c(29581,5279,4218,1917,1356,116,97,141,1714,17531,1744,1326,1208,526,
459,14,18138,17531,1744,1326,1208,526,459,14,6374,2958,8851,6374,
2958,3098,5753)
group <- c(1:8, rep(9,8), 10, rep(19,7), rep(18,3), rep(23,2), rep(22,2))
links <- data.frame(source, target, value, group)
links$group <- as.character(links$group)
sn <- sankeyNetwork(Links=links, Nodes=nodes, Source='source', Target='target',
Value='value', NodeID='name', fontSize=18,
NodeGroup = "NodeGroup",
sinksRight = FALSE,
LinkGroup = "group",
#nodeWidth = 40,
#width=1500, height=500,
#margin = list("right"=250),
iterations = FALSE)
onRender(sn,
'
function(el, x) {
var sankey = this.sankey;
var path = sankey.link();
var nodes = d3.selectAll(".node");
var link = d3.selectAll(".link")
var width = el.getBoundingClientRect().width - 40;
var height = el.getBoundingClientRect().height - 40;
window.dragmove = function(d) {
d3.select(this).attr("transform",
"translate(" + (
d.x = Math.max(0, Math.min(width - d.dx, d3.event.x))
) + "," + (
d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))
) + ")");
sankey.relayout();
link.attr("d", path);
};
nodes.call(d3.drag()
.subject(function(d) { return d; })
.on("start", function() { this.parentNode.appendChild(this); })
.on("drag", dragmove));
}
'
)
Node positions can be moved in the Viewer window on RStudio, however the resolution is low when using the Export > Save as Image option, or when using a screenshot:
I have also tried exporting the sankey plot to html file, in order to customise and export as an image using the webshot package. However, changing the horizontal position of nodes is disabled and the new node positions are not preserved in the image export:
saveWidget(sn, "SankeyNetwork.html")
library(webshot)
webshot("SankeyNetwork.html", "sn.png", delay = 0.2)
I would be grateful if anyone can suggest a way to export the customised node positions as a high-resolution image and html file. Thank you in advance for your help.

How to chage the background color of a plot in shiny?

I'm wondering if i can change the background-color of the plot or at least make it transparent allowing to inherit its parent background ,
I have tried that :
ui:
plotOutput("scatterChart",
width = "80%",
height = "294px")
server:
output$scatterChart <- renderPlot({
par(bg = "yellow")
plot(rules(), col = rainbow(25), cex = input$cex)
})
as shown here : https://stat.ethz.ch/pipermail/r-help/2003-May/033971.html
but nothing changed .
I tried that with css :
#scatterChart{
background-color:red}
i didn't get the expected result .
or :
.shiny-plot-output{
background-color:red
}
that change the entire div background and i even can't see the plot itself(i was exepecting that ).
Here is a picture :
demo
EDITED :
Based on the example that thothal gives me , i discover that the problem was on the data passed to the plot function (it just some association rules obtained using Apriori algorithm) :
rules <- reactive({
head(read.csv(input$file$datapath), input$visualization)
transactions = read.transactions(
file = file(input$file$datapath),
format = "basket",
sep = ","
)
minValue <- min(length(transactions),input$visualization)
rules <-
apriori(transactions[0:minValue],
parameter = list(
support = input$min_supp,
confidence = input$min_conf
))
return(rules)
})
Any suggestions or advice would be appreciated. Thanks.
Actually you can simply change the background color of you plot like this
library(shiny)
ui <- fluidPage(plotOutput("p"), actionButton("go", "Go"))
server <- function(input, output) {
output$p <- renderPlot({
input$go
par(bg = "navyblue")
x <- rnorm(100)
plot(x, 5 * x + rnorm(100, sd = .3), col = "white")
})
}
shinyApp(ui, server)
This produces the following plot on my machine:
As you tried the very same, I was wondering what happens if you try to create the plot outside shiny does it show (with the respective par call) a colorful background?
Maybe some other settings in you app may override this behaviour. Can you try to run my code and see what happens?
If you use another plotting library (ggplot for instance) you have to adapt and use
theme(plot.background = element_rect(...), # plotting canvas
panel.background = element_rect(...)) # panel
Update
It turns out that the culprit is arulesViz:::plot.rules, which is grid based and ignores settings set via par. To get a colored background we have to add a filled rect to the right viewport.
I forked the original repo and provided a quick fix of that:
devtools::install_github("thothal/arulesViz#add_bg_option_scatterplot")
data(Groceries)
rules <- apriori(Groceries, parameter=list(support=0.001, confidence=0.8))
## with my quick fiy you can now specify a 'bg' option to 'control'
plot(rules, control = list(bg = "steelblue")
We can use bg argument inside renderPlot:
output$plot1 <- renderPlot({
# your plot
}, bg = "red")

How to not display values in the nodes or the links in SankeyDiagram using networkD3 in R

In the sankeydiagram example below, is there anyway to hide the "Values" being shown in the diagram while hovering - both on the Nodes as well as the Links. Im basically using the sankey chart to show a stylised flow diagram, and I would like the Values not be shown to the user at all
URL <- paste0('https://cdn.rawgit.com/christophergandrud/networkD3/master/JSONdata/energy.json')
energy <- jsonlite::fromJSON(URL)
sankeyNetwork(Links = energy$links, Nodes = energy$nodes, Source = 'source',
Target = 'target', Value = 'value', NodeID = 'name',
units = 'TWh', fontSize = 12, nodeWidth = 30)
To be clear, in the screenshot below,I would still like to see the Wind-Electricitygrid, but would like 289KWH not be displayed
You can generate any text you want to be displayed in the tooltips and add it to the htmlwidgets object, then use some custom JavaScript to set the tooltip text to it...
library(jsonlite)
library(networkD3)
library(htmlwidgets)
URL <- paste0('https://cdn.rawgit.com/christophergandrud/networkD3/master/JSONdata/energy.json')
energy <- jsonlite::fromJSON(URL)
# generate the text you want to display
energy$links$name <-
paste0(energy$nodes$name[energy$links$source + 1],
" -> ", energy$nodes$name[energy$links$target + 1])
sn <- sankeyNetwork(Links = energy$links, Nodes = energy$nodes, Source = 'source',
Target = 'target', Value = 'value', NodeID = 'name',
units = 'TWh', fontSize = 12, nodeWidth = 30)
# add the names back into the links data because sankeyNetwork strips it out
sn$x$links$name <- energy$links$name
# add onRender JavaScript to set the title to the value of 'name' for each link
sn <- htmlwidgets::onRender(
sn,
'
function(el, x) {
d3.selectAll(".link").select("title foreignObject body pre")
.text(function(d) { return d.name; });
}
'
)
# display the result
sn

R visNetwork: create new type of edges

I want to create a PAG(parental ancestral graph) with visNetwork for my shiny app.
In order to do that i have to create edges that have both circles and arrows.
According to the visNetwork package i can convert the arrows to circles like this
visNetwork(nodes, edges) %>%
visEdges(arrows = list(to = list(enabled = TRUE,
scaleFactor = 2, type = 'circle')))
But i want to have both an arrow and a circle, or two circles in one edge like in this picture
PAG
The arrows.from.type and arrows.to.type seem to be working but i now i have this problem.
I want to draw this graph according to an adjacency matrix
So i have this code
i = 1
j = 1
for(i in i:ncol(results))
{
j = i
for(j in j:nrow(results))
{
if(results[j,i]==1)
{
dashBoard = c(dashBoard,TRUE)
colorBoard = c(colorBoard, "green")
if(results[i,j]==1)
{
fromtest <- c(fromtest,Cnames[i])
totest <- c(totest,Rnames[j])
arrfrom <-c(arrfrom,"circle")
arrto<-c(arrto,"circle")
}
else if(results[i,j]==2)
{
fromtest<-c(fromtest,Cnames[i])
totest<-c(totest,Rnames[j])
arrfrom <-c(arrfrom,"circle")
arrto<-c(arrto,"arrow")
}}
That goes on for every possible combination except 1,1 and 1,2
In the end the edges are printed like that
edgesprint <-data.frame(from = fromtest,
to = totest,
arrows.from.type=arrfrom,
arrows.to.type=arrto,
dashes = dashBoard,
physics = FALSE,
smooth = FALSE,
width = 3,
shadow = TRUE,
color = list(color = colorBoard, highlight = "red", hover = "green"),
links = links)
This method works good but sometimes without changing any code i get this error
error in data.frame arguments imply differing number of rows
You can set individual arrow types in the edges data frame by adding columns arrows.to.type and arrows.from.type:
library(visNetwork)
library(magrittr)
nodes <- data.frame(id=c("a","b","c","d"), label=c("a","b","c","d"))
edges <- data.frame(
from = c("a","a","a"),
to = c("b","c","d"),
arrows.from.type = c(NA,"circle","circle"),
arrows.to.type = c("arrow","circle",NA)
)
visNetwork(nodes, edges)
Result:
This approach works for all other attributes you can set through visNodes and visEdges. See here for an example.

Change Font Size on rCharts Sankey Diagram

I'm using the following code to create a Sankey Diagram using rCharts. I wish to increase the font size of the text printed on the Sankey Diagram. I can't find a manual to show me how to do this. Thoughts?
rm(list = ls())
require(reshape)
require(rCharts)
require(rjson)
target <- c('TMF', 'TMF', 'TMF','Evaporation','Mill Reclaim','Void Losses','Seepage')
source <- c('Precipitation & Run Off','Slurry','Other','TMF','TMF','TMF','TMF')
value <- c(638,1610,755,118,1430,466,2)
x <- data.frame(target,source,value)
sankeyPlot <- rCharts$new()
sankeyPlot$set(
data = x,
nodeWidth = 10,
nodePadding = 10,
layout = 32,
width = 1100,
height = 675,
units = "cubic metres",
title = "Sankey Diagram"
)
sankeyPlot$setLib('http://timelyportfolio.github.io/rCharts_d3_sankey')
sankeyPlot
Based on this answer you can add scripts to customize your plots. To change the text-size, you could add:
sankeyPlot$setTemplate(
afterScript = "
<script>
d3.selectAll('#{{ chartId }} svg text')
.style('font-size', '55')
</script>
")
I was able to change the font size after creating the sankey diagram by setting the fontSize option:
#create sankey diagram
p<-sankeyNetwork(...)
#the default font size
> p$x$options$fontSize
[1] 7
#set desired font size
p$x$options$fontSize<-10

Resources