Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

r - Place text values to right of sankey diagram

Is there a trick to placing text on a sankey diagram rendered using networkD3? I would like to have the values of the endpoints be displayed as text to the right of their boxes. I realize that hovering over the boxes displays the value, but as the boxes get smaller it would be much easier in many cases to portray the information if the values were always visible on the side.

Here is an example; I was able to kinda hack it by adding the values as part of the labels, but it would be much better to have the values displayed to the right of the diagram.

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)

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Sorry, I just now ran across this. This would be a great use for the new onRender function in htmlwidgets. I tried to comment inline to explain the couple of lines of added JavaScript to move the node text. networkD3 filters in these lines to change the placement to right or left based on width. We will just apply this to all of the text so it will be to the right of our node rectangles.

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)



#################### move leaf node text right ################
# for this to work
#   install the newest htmlwidgets
#   devtools::install_github("ramnathv/htmlwidgets")

library(htmlwidgets)
#  add margin left since we'll need extra room
#   if you are wondering why margin left,
#   I think we just discovered a bug
sn <- sankeyNetwork(
  Links=links, Nodes=nodes, Source='src', Target='target',
  Value='value', NodeID='name', fontSize=16,
  width=600, height=300,
  # give us so room for our newly aligned labels
  margin = list("left"=100)
)
# see how it looks
sn

# now let's use the new htmlwidget function
#  onRender
onRender(
  sn,
'
function(el,x){
  // select all our node text
  var node_text = d3.select(el)
    .selectAll(".node text")
    //and make them match
    //https://github.com/christophergandrud/networkD3/blob/master/inst/htmlwidgets/sankeyNetwork.js#L180-L181
    .attr("x", 6 + x.options.nodeWidth)
    .attr("text-anchor", "start");
}
'
)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...