Put line break in node labels in networkD3 sankey diagram
Asked Answered
S

1

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.

Superconductivity answered 22/6, 2017 at 13:20 Comment(1)
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 github.com/christophergandrud/networkD3/issuesObservable
O
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

Observable answered 8/9, 2018 at 0:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.