Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change node and link colors in R googleVis sankey chart

How can node and link colors be changed in R googleVis sankey chart? And link having the same color as its originating node?

library(googleVis)
datSK <- data.frame(From=c(rep("A",3), rep("B", 3)),
                To=c(rep(c("X", "Y", "Z"),2)),
                Weight=c(5,7,6,2,9,4))

Sankey <- gvisSankey(datSK, from="From", to="To", weight="Weight",
                 options=list(
                   sankey="{link: {color: { fill: '#d799ae' } },
                        node: { color: { fill: '#a61d4c' },
                        label: { color: '#871b47' } }}"))
plot(Sankey)
like image 814
santoku Avatar asked Mar 31 '15 15:03

santoku


3 Answers

As soon as you have to color links from 2 originated nodes you'll need 2 colors for links. Also you have 5 nodes in total, so you'll need 5 colors for them.

Lets create 2 arrays in JSON format with colors for nodes and links

colors_link <- c('green', 'blue')
colors_link_array <- paste0("[", paste0("'", colors_link,"'", collapse = ','), "]")

colors_node <- c('yellow', 'lightblue', 'red', 'black', 'brown')
colors_node_array <- paste0("[", paste0("'", colors_node,"'", collapse = ','), "]")

Next, insert that array into options:

opts <- paste0("{
        link: { colorMode: 'source',
                colors: ", colors_link_array ," },
        node: { colors: ", colors_node_array ," }
      }" )

And, finally plot graph:

plot( gvisSankey(datSK, from="From", to="To", weight="Weight",
                     options=list(
                       sankey=opts)))

enter image description here

Note, that in options colorMode is set to 'source' which means you would like to color links from originated nodes. Alternatively, set 'target' to color links for destinated nodes

EDIT: add description for multilevel sankeys

It is a bit tricky to find how to assign colors for multilevel sankeys.

We need to create other dateframe:

datSK <- data.frame(From=c(rep("A",3), rep("B", 3), rep(c("X", "Y", "Z"), 2 )),
                To=c(rep(c("X", "Y", "Z"),2), rep("M", 3), rep("N", 3)),
                Weight=c(5,7,6,2,9,4,3,4,5,6, 4,8))

Here we have to change only arrays of colors. Command to built plot is the same Let's assume we want these colors for the nodes and links :

colors_link <- c('green', 'blue', 'yellow', 'brown', 'red')
colors_link_array <- paste0("[", paste0("'", colors_link,"'", collapse = ','), "]")

colors_node <- c('yellow', 'lightblue', 'red', 'black', 'brown', 'green', 'brown')
colors_node_array <- paste0("[", paste0("'", colors_node,"'", collapse = ','), "]")

Result would be :

enter image description here

The most trickiest part is to understand how these colors are assigned:

  1. Links are assigned in the order they appear in dataset (row_wise)

enter image description here

  1. For the nodes colors are assigned in the order plot is built.

    • From A to X, Y, Z - green
    • From X to M, N - blue
    • From Y to M, N - yellow
    • From Z to M, N - brown
    • From B to X, Y, Z - red

More detailed information on how to format sankey diagram : https://developers.google.com/chart/interactive/docs/gallery/sankey

like image 122
Vadym B. Avatar answered Nov 15 '22 14:11

Vadym B.


I know this is older but in case anyone else is ever stuck on this - I figured out how to make the proper order and generate a string of color nodes so you can have custom colors for certain labels. Shout out to @vadym-b for the data and explaining about the order. Check it out:

#convert to list combined of source and target for color order
# edges is a dataframe from @vadym-b's answer above
edges <- data.frame(From=c(rep("A",3), rep("B", 3), rep(c("X", "Y", "Z"), 2 )),
                    To=c(rep(c("X", "Y", "Z"),2), rep("M", 3), rep("N", 3)),
                    Weight=c(5,7,6,2,9,4,3,4,5,6, 4,8))

#we have to make the order right - you need a list
# that is a combination of From, To, From, To, From, To
nc.df <- c()
for (i in 1:nrow(edges)) {
  nc.df <- c(nc.df, as.character(edges$From[i]), as.character(edges$To[i]))
}

#the actualy parsing - get the unique list and return
# colors based on what the source or target value is
nodeColor <- sapply(unique(nc.df), function(r) {
  if (grepl('A',r)) return('red')
  if (grepl('B',r)) return('red')
  if (grepl('Z',r)) return('green')
  if (grepl('X',r)) return('green')
  if (grepl('Y',r)) return('purple')
  if (grepl('M',r)) return('blue')
  if (grepl('N',r)) return('blue')
  #return a default color if you like
  return('black')
})

#make a sankey
library(googleVis)

# put the color list in a collapsed string
sankey <- gvisSankey(
  edges, 
  chartid = 'Sankey', 
  from="From", 
  to="To", 
  weight="Weight", 
  options=list(
    sankey = paste0("{
      iterations: 0,
      link: {
        colorMode: 'gradient'
      },
      node: {
        colors: ['",paste(nodeColor,collapse="','"),"']
      }
    }")
  )
)

plot(sankey)

Sankey with custom colors

like image 23
Michael Tallino Avatar answered Nov 15 '22 13:11

Michael Tallino


I have put on github a piece of code that does that.

#TOPLOTS[,1] = from ; TOPLOTS[,1] = to
names_pahtwayorder<-unlist(data.frame(t(TOPLOTs[,1:2])))
names_pahtwayorder<-names_pahtwayorder[!duplicated(names_pahtwayorder)]
names(names_pahtwayorder)<-NULL; names_pahtwayorder

https://github.com/SkanderMulder/ExtractIPA/blob/master/functionSankey.r

like image 1
STM Avatar answered Nov 15 '22 15:11

STM