ggraph
ggraph copied to clipboard
Remove isolated nodes from dynamic layout in ggraph plot
I want to plot friendships that persist over multiple waves, and keep the nodes in the same coordinates for each plot. I'm able to use ggraph and graphlayouts' dynamic layout to keep the nodes in the same positions over four waves, but I want to remove the nodes over time that lose their ties. This is an example of what I have done so far:
library(dplyr)
library(magrittr)
library(ggplot2)
library(igraph)
library(tidygraph)
library(ggraph)
library(viridis)
library(gridExtra)
set.seed(1234)
gtest <- erdos.renyi.game(100, 0.03, type = "gnp", directed = TRUE,
loops = FALSE) %>%
set_vertex_attr("label", value = 1:100)
g_nodes <- get.data.frame(gtest, what = "vertices") %>%
mutate(sex = sample(0:1, n(), replace = TRUE),
sex = as.character(sex))
g_edges1 <- get.edgelist(gtest) %>% as.data.frame()
g_edges2 <- sample_n(g_edges1, 130, replace = FALSE)
g_edges3 <- sample_n(g_edges2, 70, replace = FALSE)
g_edges4 <- sample_n(g_edges3, 20, replace = FALSE)
g1 <- graph_from_data_frame(d=g_edges1, vertices = g_nodes, directed = TRUE)
g2 <- graph_from_data_frame(d=g_edges2, vertices = g_nodes, directed = TRUE)
g3 <- graph_from_data_frame(d=g_edges3, vertices = g_nodes, directed = TRUE)
g4 <- graph_from_data_frame(d=g_edges4, vertices = g_nodes, directed = TRUE)
gList <- list(g1, g2, g3, g4)
xy <- graphlayouts::layout_as_dynamic(gList,alpha = 0.2)
pList <- vector("list",length(gList))
for(i in 1:length(gList)){
pList[[i]] <- ggraph(gList[[i]],layout="manual",x=xy[[i]][,1],y=xy[[i]][,2])+
geom_edge_link(color = "black", alpha = 0.7,
arrow = arrow(type = "closed",
angle = 25,
length = unit(1.5, 'mm')),
end_cap = circle(1, 'mm'),
width = 0.5, show.legend = FALSE) +
geom_node_point(aes(color = factor(sex)), size = 3) +
scale_color_hue(l=40) +
theme_graph()+
theme(legend.position = "none")
}
Reduce("+",pList)+
plot_annotation(title="Friendship network",theme = theme(title = element_text(family="Arial Narrow",face = "bold",size=16)))
Which gives me this plot:
This is what I want, except for plots 2-4 I want to delete the nodes with no edges. I've tried also deleting the isolates from the individual graph functions such as:
g1 <- graph_from_data_frame(d=g_edges1, vertices = g_nodes, directed = TRUE)
g2 <- graph_from_data_frame(d=g_edges2, vertices = g_nodes, directed = TRUE) %>%
delete.vertices(., which(degree(.)==0))
g3 <- graph_from_data_frame(d=g_edges3, vertices = g_nodes, directed = TRUE) %>%
delete.vertices(., which(degree(.)==0))
g4 <- graph_from_data_frame(d=g_edges4, vertices = g_nodes, directed = TRUE) %>%
delete.vertices(., which(degree(.)==0))
But then I get this error when I try to run the plot:
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 100, 98
Any ideas on how I can remove the isolates within the plot itself?
change the code within the for loop to
rem_nodes <- which(degree(gList[[i]])==0)
ggraph(delete.vertices(gList[[i]],rem_nodes),
layout="manual",x=xy[[i]][-rem_nodes,1],y=xy[[i]][-rem_nodes,2])+
geom_edge_link(color = "black", alpha = 0.7,
arrow = arrow(type = "closed",
angle = 25,
length = unit(1.5, 'mm')),
end_cap = circle(1, 'mm'),
width = 0.5, show.legend = FALSE) +
geom_node_point(aes(color = factor(sex)), size = 3) +
scale_color_hue(l=40) +
theme_graph()+
theme(legend.position = "none")
Alternatively use filter = !node_is_isolated()
inside the aes()
function for geom_node_point()