LDT
LDT

Reputation: 3088

Specify node shape and label in a bipartite network with ggraph

I want to plot an adjacent matrix with ggraph. My data looks like this

set.seed(43);
check <- matrix(rnorm(10), nrow = 5,ncol = 4, dimnames = list(c("AL","CH","CZ","DN","SC"), c("GR","EN","GE","FR")))

            GR          EN          GE          FR
AL -0.03751376 -0.27743280 -0.03751376 -0.27743280
CH -1.57460441  0.38643441 -1.57460441  0.38643441
CZ -0.48596752 -0.06040412 -0.48596752 -0.06040412
DN  0.46518623 -0.68617976  0.46518623 -0.68617976
SC -0.90409807 -1.90613679 -0.90409807 -1.90613679

I want to plot interactions using a bipartite network but I find it hard to specify the labels at the x-axis at the top and the bottom. Also I want to change the shape of the nodes. I want to see a blue square on the top and a green circle at the bottom.

ggraph(check, layout = "bipartite") + 
  geom_edge_link0(aes(edge_width = weight),edge_colour = "grey66") +
  geom_node_point()

enter image description here

Any help or comment are highly appreciated.

Upvotes: 0

Views: 848

Answers (1)

teunbrand
teunbrand

Reputation: 37953

If you create a layout before passing the adjacency matrix to the plot, you can inspect the variables that are in there.

library(ggraph)
#> Loading required package: ggplot2
set.seed(43);
check <- matrix(rnorm(10), nrow = 5,ncol = 4, 
                dimnames = list(c("AL","CH","CZ","DN","SC"), 
                                c("GR","EN","GE","FR")))

(layout <- create_layout(check, "bipartite"))
#>     x y  type name .ggraph.orig_index circular .ggraph.index
#> 1 0.5 1 FALSE   AL                  1    FALSE             1
#> 2 1.5 1 FALSE   CH                  2    FALSE             2
#> 3 2.5 1 FALSE   CZ                  3    FALSE             3
#> 4 3.5 1 FALSE   DN                  4    FALSE             4
#> 5 4.5 1 FALSE   SC                  5    FALSE             5
#> 6 1.0 0  TRUE   GR                  6    FALSE             6
#> 7 2.0 0  TRUE   EN                  7    FALSE             7
#> 8 3.0 0  TRUE   GE                  8    FALSE             8
#> 9 4.0 0  TRUE   FR                  9    FALSE             9

We can see in the layout above that the type variable seems to encode which part of the bipartite graph is on top and which on the bottom. Hence, we can use the mapping in the node layer to let the shape and colour be dependent on the type variable.

g <- ggraph(layout) + 
  geom_edge_link0(aes(edge_width = weight),edge_colour = "grey66") +
  geom_node_point(aes(shape = type, colour = type), size = 6) +
  scale_colour_manual(values = c("blue", "green")) +
  scale_shape_manual(values = c(15, 19))
g

Getting the right labels on the x-axis may be a little bit involved, but essentially you can extract break and label information from the layout.

g + scale_x_continuous(
  breaks = layout$x[!layout$type],
  labels = layout$name[!layout$type],
  position = "top",
  sec.axis = dup_axis(
    breaks = layout$x[layout$type],
    labels = layout$name[layout$type]
  )
) +
  theme(axis.text = element_text())

Created on 2021-07-10 by the reprex package (v1.0.0)

Note that this may not work for any graph, but it works due to properties of bipartite graphs in particular. A more general strategy for labelling nodes is to use geom_node_text():

g + geom_node_text(aes(label = name, 
                       y = y + ifelse(type, -0.05, 0.05)), 
                   vjust = "outward")

Upvotes: 3

Related Questions