Search code examples
rvisualizationggraph

Unable to color lines by group on a circular dendogram using R/ggraph


I've created a circular dendogram using R and the ggraph package. I have my labels and nodes correctly colored by "group". However, I'm unsure how to color the lines by "colors" (my color column). Currently I can change the line color to a single color (e.g. "red"), though I can't color them dynamically by column "colors".

My code is based on code from the r-graph gallery website. As you can see from my datafiles, I've tried adding a "colors" column and then calling that in my ggraph call but that gives me the following error:

Error in `geom_edge_diagonal(colour = colors)`:
! Problem while setting up geom aesthetics.
ℹ Error occurred in the 1st layer.
Caused by error in `rep()`:
! attempt to replicate an object of type 'closure'

Here is my code:

library(ggraph)
library(igraph)
library(tidyverse)
library(RColorBrewer)

d1 = read.csv("~/data1.csv", sep=",")
d2 = read.csv("~/data2.csv", sep=",")

edges=rbind(d1, d2)

# create a vertices data.frame. One line per object of our hierarchy
vertices = data.frame(
  name = unique(c(as.character(edges$from), as.character(edges$to))) , 
  value = runif(78)
) 

# Let's add a column with the group of each name. It will be useful later to color points
vertices$group = edges$from[ match( vertices$name, edges$to, edges$colors ) ]

#Let's add information concerning the label we are going to add: angle, horizontal adjustement and potential flip
#calculate the ANGLE of the labels
vertices$id=NA
myleaves=which(is.na( match(vertices$name, edges$from, edges$colors) ))
nleaves=length(myleaves)
vertices$id[ myleaves ] = seq(1:nleaves)
vertices$angle= 90 - 360 * vertices$id / nleaves

# calculate the alignment of labels: right or left
# If I am on the left part of the plot, my labels have currently an angle < -90
vertices$hjust<-ifelse( vertices$angle < -90, 1, 0)

# flip angle BY to make them readable
vertices$angle<-ifelse(vertices$angle < -90, vertices$angle+180, vertices$angle)

# Create a graph object
mygraph <- graph_from_data_frame( edges, vertices=vertices )

# Make the plot
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) + 
  geom_edge_diagonal(colour=colors) +
  scale_edge_colour_distiller(palette = "RdPu") +
  geom_node_text(aes(x = x*1.12, y=y*1.12, filter = leaf, label=name, angle = angle, colour=group, hjust=hjust), size=6) +
  geom_node_point(aes(filter = leaf, x = x*1.07, y=y*1.07, colour=group, alpha=.2, size=2)) +
  scale_colour_manual(values= rep( brewer.pal(7,"Paired") , 30)) +
  scale_size_continuous( range = c(0.1,17) ) +
  theme_void() +
  theme(
    legend.position="none",
    plot.margin=unit(c(0,0,0,0),"cm"),
  ) +
  expand_limits(x = c(-1.3, 1.3), y = c(-1.3, 1.3))

Here are two minimal examples of the code used:

data1.csv

from,to,colors
origin,group1,color1
origin,group2,color1
origin,group3,color1
origin,group4,color2
origin,group5,color2
origin,group6,color3
origin,group7,color3
origin,group8,color4
origin,group9,color4

data2.csv

from,to,colors
group1,"test1",color1
group2,"test2",color1
group3,"test3",color1
group4,"test4",color2
group5,"test5",color2
group6,"test6",color3
group7,"test7",color3
group8,"test8",color4
group9,"test9",color4

I believe the following line is the one I need help with (inside my ggraph call):

geom_edge_diagonal(colour=colors) +

If it helps, my question is the same as asking how to color lines by group on the example code I used, taken from r-graph gallery.

Any help is appreciated.


Solution

  • The suggestion in my earlier comments, to use aes(), did solve for the error you had identified. You just realized you had yet another problem. We solve for that by changing from scale_edge_color_distiller to scale_edge_color_brewer as distiller is looking for a continuous variable.

    Note, I've also set up so your data is reproducible. Consider using dput() in the future when you provide your data set to support question asked.

    
    d1 <- tribble(
        ~from,~to,~colors,
    "origin","group1","color1",
    "origin","group2","color1",
    "origin","group3","color1",
    "origin","group4","color2",
    "origin","group5","color2",
    "origin","group6","color3",
    "origin","group7","color3",
    "origin","group8","color4",
    "origin","group9","color4")
    
    d2 <- tribble(
        ~from, ~to, ~colors,
    "group1","test1","color1",
    "group2","test2","color1",
    "group3","test3","color1",
    "group4","test4","color2",
    "group5","test5","color2",
    "group6","test6","color3",
    "group7","test7","color3",
    "group8","test8","color4",
    "group9","test9","color4")
    
    
    
    edges=rbind(d1, d2)
    
    # create a vertices data.frame. One line per object of our hierarchy
    vertices = data.frame(
        name = unique(c(as.character(edges$from), as.character(edges$to))) , 
        value = runif(19)
    ) 
    
    # Let's add a column with the group of each name. It will be useful later to color points
    vertices$group = edges$from[ match( vertices$name, edges$to, edges$colors ) ]
    
    #Let's add information concerning the label we are going to add: angle, horizontal adjustement and potential flip
    #calculate the ANGLE of the labels
    vertices$id=NA
    myleaves=which(is.na( match(vertices$name, edges$from, edges$colors) ))
    nleaves=length(myleaves)
    vertices$id[ myleaves ] = seq(1:nleaves)
    vertices$angle= 90 - 360 * vertices$id / nleaves
    
    # calculate the alignment of labels: right or left
    # If I am on the left part of the plot, my labels have currently an angle < -90
    vertices$hjust<-ifelse( vertices$angle < -90, 1, 0)
    
    # flip angle BY to make them readable
    vertices$angle<-ifelse(vertices$angle < -90, vertices$angle+180, vertices$angle)
    
    # Create a graph object
    mygraph <- graph_from_data_frame( edges, vertices=vertices )
    
    # Make the plot
    ggraph(mygraph, layout = 'dendrogram', circular = TRUE) + 
        geom_edge_diagonal(aes(colour=colors)) +
        #scale_edge_colour_distiller(palette = "RdPu") +
        scale_edge_colour_brewer(palette = "RdPu") +
        geom_node_text(aes(x = x*1.12, y=y*1.12, filter = leaf, label=name, angle = angle, colour=group, hjust=hjust), size=6) +
        geom_node_point(aes(filter = leaf, x = x*1.07, y=y*1.07, colour=group, alpha=.2, size=2)) +
        scale_colour_manual(values= rep( brewer.pal(7,"Paired") , 30)) +
        scale_size_continuous( range = c(0.1,17) ) +
        theme_void() +
        theme(
            legend.position="none",
            plot.margin=unit(c(0,0,0,0),"cm"),
        ) +
        expand_limits(x = c(-1.3, 1.3), y = c(-1.3, 1.3))
    

    enter image description here