0

I'm working on plotting a network graph, and am having trouble reading the edge labels. Is there a way to define a background color or opaque area behind the edge labels to make them more readable? Thanks!

```
g_ex <- tibble::tibble(from = rep("a", 3), to = c("x", "y", "z"), weight = seq(0, 0.2, 0.1)) %>% 
  igraph::graph_from_data_frame(.)

plot.igraph(g_ex, edge.label = igraph::get.edge.attribute(g_ex, "weight"))
```
[![Directed graph with one parent node "a" and three child nodes "x", "y", & "z". Edges have weights of 0.0, 0.1, & 0.2, respectively.][1]][1]


  [1]: https://i.stack.imgur.com/asCxe.png

UPDATE

One important consideration I neglected in initial example is that vertices need to be conditionally formatted based on a vertex attribute. Updated reprex below, differences in node size can be ignored.

'''
# load pkgs
library(tidyverse)
library(plotrix)
library(igraph)

# define and register ellipse w/ igraph, from https://stackoverflow.com/a/48469289/9806500
myellipse <- function(coords, v = NULL, params) {
  vertex.color <- params("vertex", "color")
  if (length(vertex.color) != 1 && !is.null(v)) {
    vertex.color <- vertex.color[v]
  }
  vertex.size <- 1 / 30 * params("vertex", "size")
  if (length(vertex.size) != 1 && !is.null(v)) {
    vertex.size <- vertex.size[v]
  }
  
  plotrix::draw.ellipse(
    x = coords[, 1],
    y = coords[, 2],
    a = vertex.size,
    b = vertex.size / 2,
    col = vertex.color
  )
}

igraph::add_shape("ellipse", clip = shapes("circle")$clip, plot = myellipse)


# define graph
df_e <- tibble::tibble(from = rep("a", 3), to = c("x", "y", "z"), weight = seq(0, 0.2, 0.1))

df_v <- tibble::tibble(name = c("a", "x", "y", "z"), shape = c("square", "ellipse", "ellipse", "ellipse"))

g_ex <- igraph::graph_from_data_frame(d = df_e, vertices = df_v)

# plot
igraph::plot.igraph(g_ex, edge.label = igraph::get.edge.attribute(g_ex, "weight"), vertex.shape = igraph::get.vertex.attribute(g_ex, "shape"))
```

Updated example with parent square vertex and children elliptical vertices.

M. Wood
  • 450
  • 4
  • 13
  • 1
    Please take a look at this earlier question. [How to separate edge label from edge in igraph?](https://stackoverflow.com/a/56889192/4752675) – G5W Dec 28 '22 at 21:25
  • 2
    The ggraph package gives you more control over the aesthetics. – stomper Dec 28 '22 at 21:55
  • Thanks @G5W, will give that layout suggestion a try. Must have overlooked that question in an earlier results query. – M. Wood Dec 30 '22 at 13:06
  • Thanks @stomper. Long story short is that I'm using igraph to procedurally generate graphs with structural equation model conventions to describe proposed relationships between variables. As such, I've using `{plotrix}` package to specify ellipse-shaped points for plotting based on https://stackoverflow.com/a/48469289/9806500. Happen to know if ggraph will use these self-defined shapes? – M. Wood Dec 30 '22 at 13:13

1 Answers1

1

You can get full control over the aesthetics of your graph using ggraph, and to my eye a more professional end result. Here's a quick demo using your example graph:

library(ggraph)

ggraph(g_ex, layout = "igraph", algorithm = "nicely") +
  geom_edge_link(aes(label = weight), angle_calc = "along", vjust = -0.5,
                 label_size = 6, arrow = arrow(length = unit(3, "mm")), 
                 end_cap = circle(10, "mm"), alpha = 0.5) +
  geom_node_point(shape = 21, fill = "#FFD080", size = 20, color = "orange") +
  geom_node_text(aes(label = name), size = 8) +
  theme_graph() +
  coord_equal(clip = "off") +
  theme(panel.background = element_blank(),
        plot.background = element_rect(color = NA, fill = "gray98"))

enter image description here


Update

To get elliptical nodes with different fill colors, we can do:

ggraph(g_ex, layout = "igraph", algorithm = "nicely") +
  geom_edge_link(aes(label = weight), angle_calc = "along", vjust = -0.5,
                 label_size = 6, arrow = arrow(length = unit(3, "mm")), 
                 end_cap = ellipsis(10, 5, "mm"), 
                 start_cap = ellipsis(10, 5, "mm"),
                 alpha = 0.5) +
  geom_node_circle(aes(r = 0.2, fill = factor(name), 
                       color = after_scale(scales::alpha(fill, 1))), 
                   alpha = 0.5) +
  geom_node_text(aes(label = name), size = 6) +
  theme_graph() +
  coord_fixed(0.5) +
  theme(panel.background = element_blank(),
        plot.background = element_rect(color = NA, fill = "gray98"),
        legend.position = 'none')

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thanks, I agree the aesthetics are an advance on `igraph.plot()` . One sticky wicket is that I've defined my own point aesthetic with `{plotrix}` for the graph I'm writing (see comment above). Happen to know if `{ggraph}` can accomodate? – M. Wood Dec 30 '22 at 13:17
  • Thanks @Allan , is there a way to do this vertex formatting conditional on a graph vertex attribute? I've provided an update to my reprex above with an example. – M. Wood Jan 02 '23 at 14:13