Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Put line break in node labels in networkD3 sankey diagram

++++++++++++++++

Update: I think the answer to my question is that you can't put line breaks in. A colleague pointed out to me the node labels are SVG blocks, which don't support line breaks.

++++++++++++++++

How do I put a line break into the node labels for a sankey diagram produced using the networkD3 R package?

Borrowing the example from Place text values to right of sankey diagram I can add values to the lables:

library(networkD3)
library(data.table)
set.seed(1999)
links <- data.table(
  src = rep(0:4, times=c(1,1,2,3,5)),
  target = sample(1:11, 12, TRUE),
  value = sample(100, 12)
)[src < target, ]  # no loops
nodes <- data.table(name=LETTERS[1:12])

#### Need to hover to get counts
##sankeyNetwork(Links=links, Nodes=nodes, Source='src', Target='target',
##  Value='value', NodeID='name', fontSize=16)

## Add text to label
txt <- links[, .(total = sum(value)), by=c('target')]
nodes[txt$target+1L, name := paste0(name, ' (', txt$total, ')')]

## Displays the counts as part of the labels
sankeyNetwork(Links=links, Nodes=nodes, Source='src', Target='target',
  Value='value', NodeID='name', fontSize=16, width=600, height=300)

I hoped that I could naively adjust the paste0 to include a line break character, such as:

 name := paste0(name, "\n ", txt$total)

or

name := paste0(name, "<br/> ", txt$total)

But I haven't been able to get anything to work, and my JavaScript is too rusty to try and fix it once it is produced.

like image 455
edsherman Avatar asked Jun 22 '17 13:06

edsherman


1 Answers

You could replace the SVG text elements with <foreignObject> blocks of text/html. This example would need a lot of additional formatting/positioning to be useful, but it demonstrates that it is possible...

library(networkD3)
library(htmlwidgets)
library(data.table)

set.seed(1999)
links <- data.table(
  src = rep(0:4, times=c(1,1,2,3,5)),
  target = sample(1:11, 12, TRUE),
  value = sample(100, 12)
)[src < target, ]  # no loops
nodes <- data.table(name=LETTERS[1:12])

## Add text to label
txt <- links[, .(total = sum(value)), by=c('target')]
nodes[txt$target+1L, name := paste0(name, '<br>(', txt$total, ')')]

## Displays the counts as part of the labels
sn <- sankeyNetwork(Links=links, Nodes=nodes, Source='src', Target='target',
              Value='value', NodeID='name', fontSize=16, width=600, height=300)

onRender(sn,
         '
  function(el,x) {
    d3.selectAll(".node text").remove()
    d3.selectAll(".node")
      .append("foreignObject")
      .attr("width", 100)
      .attr("height", 50)
      .html(function(d) { return d.name; })
  }
  '
)

enter image description here

like image 180
CJ Yetman Avatar answered Sep 20 '22 17:09

CJ Yetman