14

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

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.

CJ Yetman
  • 8,373
  • 2
  • 24
  • 56
edsherman
  • 141
  • 4
  • 3
    You are correct... the node labels are SVG text elements, and they don't natively support line breaks. There are ways to achieve it, but probably not without modifying the underlying JavaScript in networkD3. If you think it's a worthy, widely useful feature, please submit a feature request at https://github.com/christophergandrud/networkD3/issues – CJ Yetman Jun 30 '17 at 10:32

1 Answers1

4

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

CJ Yetman
  • 8,373
  • 2
  • 24
  • 56