Hi! And welcome to the forum,
I see that the question is still open. Apologies for late answer, but I had to look into some documentation as well. For networks graphs, R is not always friendly to find the right plotting options. As for myself, I only incidentally use network graphs, and never the circular type, I used your data, but lead it through my own workflow. In this case I started with a tidy tibble and use tidygraph
to make the node and edge frames.
Some remarks
- seizing the nodes requires seizing information. There is none in your data, I could see. I use a centrality-measure in this case (squared it to make the differences more pronounced, but up to you)
- I don't know the edge type used in your example graphs. I tweaked the arrow-parameters a bit, but in your case you have double arrows, which make it fuzzy. Therefore, it looks a bit ugly
- plotting the labels ouside the circle, I could not find anything in the documentation of
ggraph
to do so. A way to work around this is to extract thex-y-coordinates
usinglayer_data()
fromggplot()
and then just make a new tibble where you extend the 'circle'. See code-chunck below onnode_circle <- ...
Tune yourself with the parameters to get the plot size you want. - Your label names are long, so I needed to tweak with the plot area and switching of
clip
in the coordinate frame-work
It still is not where you want to be, but hopefully this gives you some hooks how to tune either data or code to bring you closer to what you want to achieve.
JW
#my workflow
#make data tidy
require(tidygraph,warn.conflicts = FALSE)
#> Loading required package: tidygraph
#> Warning: package 'tidygraph' was built under R version 4.0.5
require(ggraph, warn.conflicts = FALSE)
#> Loading required package: ggraph
#> Warning: package 'ggraph' was built under R version 4.0.5
#> Loading required package: ggplot2
#> Warning: package 'ggplot2' was built under R version 4.0.3
require(igraph, warn.conflicts = FALSE)
#> Loading required package: igraph
#> Warning: package 'igraph' was built under R version 4.0.3
require(dplyr, warn.conflicts = FALSE)
#> Loading required package: dplyr
#> Warning: package 'dplyr' was built under R version 4.0.4
require(tibble, warn.conflicts = FALSE)
#> Loading required package: tibble
#> Warning: package 'tibble' was built under R version 4.0.4
require(tidyr, warn.conflicts = FALSE)
#> Loading required package: tidyr
#> Warning: package 'tidyr' was built under R version 4.0.4
#restructure your data in a tidy tibble
tidy_data <- data %>% rownames_to_column() %>%
as_tibble() %>%
pivot_longer(2:24, names_to = "species", values_to = "value") %>%
filter(!is.na(value), value>0) #leave out the ones with no edges
graph_data <- as_tbl_graph(tidy_data)
#first make a simple graph to have the basic plotting
my_simple_graph <- graph_data %>% ggraph(layout = "linear", circular = TRUE)+
geom_node_point(aes(size = centrality_degree()^2 ))+
geom_edge_link0(aes(width = value*10),colour = "black") +
theme_void()+
theme(legend.position = "none")
#extract the node-values from the circle and extend outside
node_circle <- layer_data(my_simple_graph, i=1L ) %>%
left_join(my_simple_graph$data) %>%
select(x,y,name) %>%
transmute(label = name,
xe = sqrt(1.2)*x, #move outwards by 10%
ye = sqrt(1.2)*y,
hjust = if_else(xe > 0, 0, 1), #left or right h_just depending on circle position
vjust = if_else(ye > 0, 1, -1))
#> Joining, by = c("x", "y")
my_graph <- graph_data %>% ggraph(layout = "linear", circular = TRUE)+
geom_node_point(aes(size = centrality_degree()^2 ))+
#geom_node_text(aes(size =6, label = name),family="serif")+
geom_edge_link0(aes(width = value*10),colour = "black",
arrow = arrow(angle = 2, length = unit(4,"cm"),
ends = "last", type = "closed")) +
scale_size(range = c(1,10))+
theme_void()+
theme(legend.position = "none")
my_graph + geom_text(aes(x = xe, y = ye,label = label, hjust = hjust, vjust = vjust ),
size = 4, family="serif", data = node_circle) +
coord_cartesian(ylim = c(-1.1, 1.1), xlim = c(-1.2, 1.2), clip = "off") +
theme(plot.margin = margin(0,1.5,0,1.5,"cm"))