user2167741
user2167741

Reputation: 299

Pushing left labels to the left of the nodes in Sankey diagram

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)


Upvotes: 0

Views: 1817

Answers (1)

CJ Yetman
CJ Yetman

Reputation: 8848

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

Upvotes: 4

Related Questions