Electrino
Electrino

Reputation: 2890

Colouring nodes using graph and tidygraph in R?

I recently asked this question about how to colour nodes by variable. And the code works great. However, I'm back trying to colour the terminal nodes separately. For example, if I create some data, then turn them into tidygraph objects and plot them using ggraph then I get something like this:

library(tidygraph)
library(ggraph)
library(gridExtra)

pal = colorspace::sequential_hcl(palette = "Purples 3", n = 100)


# create some data for the tbl_graph
nodes <- data.frame(name = c("x4", NA, NA),
                    label = c("x4", 5, 2), 
                    value = c(10, 5, 2))

nodes1 <- data.frame(name = c("x4", "x2", NA, NA, "x1", NA, NA),
                     label = c("x4", "x2", 2,   1, "x1", 13, 7),
                     value = c(10, 8, 2, 1, 10, 13, 7))



edges <- data.frame(from = c(1,1), to = c(2,3))
edges1 <- data.frame(from = c(1, 2, 2, 1, 5, 5),
                     to    = c(2, 3, 4, 5, 6, 7))

# create the tbl_graphs
tg <- tbl_graph(nodes = nodes, edges = edges)
tg_1 <- tbl_graph(nodes = nodes1, edges = edges1)


# put into list
myList <- list(tg, tg_1)

# set colours for variables
nodenames <- unique(na.omit(unlist(lapply(myList, .%>%activate(nodes) %>% pull(name) ))))
nodecolors <- setNames(scales::hue_pal(c(0,360)+15, 100, 64, 0, 1)(length(nodenames)), nodenames)
nodecolors 

# plot function
plotFun <- function(List, colors=NULL){
  
  plot <- ggraph(List, "partition") +
    geom_node_tile(aes(fill = name), size = 0.25) +
    geom_node_label(aes(label = label, color = name)) +
    scale_y_reverse() +
    theme_void() +
    theme(legend.position = "none")
  if (!is.null(colors)) {
    plot <- plot + scale_fill_manual(values=colors) + 
      scale_fill_manual(values=colors, na.value= 'grey40')
  }
  plot
}

# create grid of plots
allPlots <- lapply(myList, plotFun, colors=nodecolors)
n <- length(allPlots)
nRow <- floor(sqrt(n))
do.call("grid.arrange", c(allPlots, nrow = nRow))

coloured trees

As you can see the named nodes are all coloured correctly, but the terminal nodes are coloured grey. I am trying to colour the terminal nodes by the corresponding value in the value column of the data. I have tried altering the scale_fill_manual function, but I cant seem to get it to work..

Any suggestions as to how I could do this?

Upvotes: 2

Views: 315

Answers (1)

Mikko Marttila
Mikko Marttila

Reputation: 11878

If I understand correctly, you want to apply a different colour mapping to the terminal nodes, mapping value to colour rather than name, and using a different colour scale altogether. ggplot2 doesn’t support that directly, but you can use e.g. ggnewscale to apply a different scale for the rest of the plot.

I simplified your example a bit to focus on the new scale application:

library(tidygraph)
library(ggraph)

nodes <- data.frame(
  name = c("x4", "x2", NA, NA, "x1", NA, NA),
  label = c("x4", "x2", 2, 1, "x1", 13, 7),
  value = c(10, 8, 2, 1, 10, 13, 7)
)

edges <- data.frame(
  from = c(1, 2, 2, 1, 5, 5),
  to = c(2, 3, 4, 5, 6, 7)
)

tg <- tbl_graph(nodes = nodes, edges = edges)

ggraph(tg, "partition") +
  geom_node_tile(aes(fill = name)) +
  geom_node_label(aes(label = label, color = name)) +
  # Apply different colour/fill scales to terminal nodes
  ggnewscale::new_scale_fill() +
  ggnewscale::new_scale_color() +
  geom_node_tile(
    data = . %>% filter(is.na(name)),
    aes(fill = value)
  ) +
  geom_node_label(
    data = . %>% filter(is.na(name)),
    aes(label = label, color = value)
  )

Upvotes: 2

Related Questions