0

Here is the code for the Sankey diagram presented here in their 'Definition' section (you can also click their CODE button in the far right of the diagram.

https://www.data-to-viz.com/graph/sankey.html

How do we make the countries in left Africa, Europe, North America, etc. move to the left of their nodes similarly how the countries on right Africa, Europe, Latin America, etc. are on the right of their nodes? Thanks.

# Libraries
library(tidyverse)
library(viridis)
library(patchwork)
library(hrbrthemes)
library(circlize)

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/13_AdjacencyDirectedWeighted.csv", header=TRUE)
# Package
library(networkD3)

# I need a long format
data_long <- data %>%
  rownames_to_column %>%
  gather(key = 'key', value = 'value', -rowname) %>%
  filter(value > 0)
colnames(data_long) <- c("source", "target", "value")
data_long$target <- paste(data_long$target, " ", sep="")

# From these flows we need to create a node data frame: it lists every entities involved in the flow
nodes <- data.frame(name=c(as.character(data_long$source), as.character(data_long$target)) %>% unique())

# With networkD3, connection must be provided using id, not using real name like in the links dataframe.. So we need to reformat it.
data_long$IDsource=match(data_long$source, nodes$name)-1 
data_long$IDtarget=match(data_long$target, nodes$name)-1

# prepare colour scale
ColourScal ='d3.scaleOrdinal() .range(["#FDE725FF","#B4DE2CFF","#6DCD59FF","#35B779FF","#1F9E89FF","#26828EFF","#31688EFF","#3E4A89FF","#482878FF","#440154FF"])'

# Make the Network
sankeyNetwork(Links = data_long, Nodes = nodes,
                     Source = "IDsource", Target = "IDtarget",
                     Value = "value", NodeID = "name", 
                     sinksRight=FALSE, colourScale=ColourScal, nodeWidth=40, fontSize=13, nodePadding=20)


CJ Yetman
  • 8,373
  • 2
  • 24
  • 56
user2167741
  • 277
  • 1
  • 10
  • 1
    Does this answer your question? [NetworkD3 Sankey Plot in R: How to switch text labels from the right to the left of the inner nodes only](https://stackoverflow.com/questions/45466632/networkd3-sankey-plot-in-r-how-to-switch-text-labels-from-the-right-to-the-left) – CJ Yetman Apr 12 '20 at 18:58
  • Well, not really. But it is close, I have to change the labels to use this - – user2167741 Apr 13 '20 at 01:55

1 Answers1

4

You have to have some way of identifying those nodes on the left versus those that are not (i.e. something to identify the nodes you want to apply special formatting to). You could add this information to your nodes data frame, then remember to add it back into the htmlwdigets object after running sankeyNetwork because only the necessary columns are retained. Then you can inject some custom JavaScript with htmlwidgets::onRender to apply a special style to only those text nodes.

library(tibble)
library(dplyr)
library(tidyr)
library(networkD3)
library(htmlwidgets)

url <- 'https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/13_AdjacencyDirectedWeighted.csv'
data <- read.table(url, header = TRUE)

data_long <- 
  data %>% 
  rownames_to_column('source') %>% 
  as_tibble() %>% 
  pivot_longer(-source, 'target') %>% 
  filter(value > 0) %>% 
  mutate(target = gsub('\\.', ' ', target)) %>% 
  mutate(source = paste0('src_', source)) %>% 
  mutate(target = paste0('trgt_', target))

nodes <- data.frame(name = unique(c(data_long$source, data_long$target)), stringsAsFactors = FALSE)
nodes <- tibble(name = unique(c(data_long$source, data_long$target)),
                target = grepl('trgt_', name))

data_long$IDsource <- match(data_long$source, nodes$name) - 1 
data_long$IDtarget <- match(data_long$target, nodes$name) - 1

nodes$name <- sub('^.*_', '', nodes$name)

ColourScal ='d3.scaleOrdinal() .range(["#FDE725FF","#B4DE2CFF","#6DCD59FF","#35B779FF","#1F9E89FF","#26828EFF","#31688EFF","#3E4A89FF","#482878FF","#440154FF"])'

sn <- sankeyNetwork(Links = data_long, Nodes = nodes,
                    Source = "IDsource", Target = "IDtarget",
                    Value = "value", NodeID = "name", 
                    sinksRight=FALSE, colourScale=ColourScal, nodeWidth=40, fontSize=13, nodePadding=20)

sn$x$nodes$target <- nodes$target

sn <- onRender(sn,
  '
  function(el) {
    d3.select(el)
      .selectAll(".node text")
      .filter(d => d.target)
      .attr("x", -6)
      .attr("text-anchor", "end");
  }
  '
)

sn

enter image description here

CJ Yetman
  • 8,373
  • 2
  • 24
  • 56
  • Yes, thanks! That's what I figured out - we need to change the labels and use that to the d3 script like filter & startsWith in onRender. – user2167741 Apr 20 '20 at 03:52