Search code examples
rggplot2ggraph

Placing geom labels outside of circular layout in ggraph/ggplot2


I am trying to generate an interaction network plot with labeled nodes in a circular layout. I have cobbled together a functional script that shows the connections I want with ggraph, but I can't figure out how to position the node labels relative to the location in the circular arrangement, so they don't overlap with the connecting lines at any location. Someone has posted a very nice solution for the same problem when using igraph (Placing vertex.label outside a circular layout in igraph); but I don't think this will work with ggraph because the way the location of the nodes is calculated seems to be different. I'd prefer to use ggraph for this, because it has a built-in legend function that makes my life easier. This is what I have so far:

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

# Create example matrix
id <- c("s01", "s02", "s03", "s04", "s05")
s01 <- c(0, 0, 0, 1, 1)
s02 <- c(0, 0, 1, 1, 1)
s03 <- c(1, 0, 0, 0, 1)
s04 <- c(0, 1, 0, 0, 0)
s05 <- c(0, 0, 0, 0, 0)
links <- data.frame(id, s01, s02, s03, s04, s05)
links <- column_to_rownames(links, var = "id")
links <- as.matrix(links)
expertise <- c("neuro", "micro", "phys", "phys", "neuro")
nodes <- data.frame(id, expertise)

# Generate igraph object
network <- graph_from_adjacency_matrix(links, weighted = NULL, mode = "undirected")

# Generate plot
ggraph(network, layout = "circle") + geom_edge_arc(color = "darkgray", strength = 0.15) + 
geom_node_point(size = 8, aes(color = nodes$expertise)) + geom_node_text(aes(label = id), nudge_y = -0.2) + 
theme_void()

This generates the following plot: enter image description here

The problem is that labels like s02 are inside the network, which becomes an issue with denser plots.

Is there a way to place all labels outside the circle of nodes? Any help would be most appreciated!


Solution

  • This is not wholly satisfactory as it requires assigning the plot as an intermediate step because the geom nudge arguments don't take a function but you can nudge the labels outwards relative to the node xy coordinates:

    library(igraph)
    library(ggplot2)
    library(ggraph)
    
    # Generate igraph object
    network <- graph_from_adjacency_matrix(links, weighted = NULL, mode = "undirected")
    
    # Generate plot
    p <- ggraph(network, layout = "circle") +
      geom_edge_arc(color = "darkgray", strength = 0.15) + 
      geom_node_point(size = 8, aes(color = nodes$expertise)) +
      theme_void()
    
    p + 
      geom_node_text(aes(label = id), nudge_x = p$data$x * .1, nudge_y = p$data$y * .1)
    

    enter image description here