I am trying to figure how to use a lat/long layout in ggraph
but can't seem to work my way through the syntax. Consider this reprex with some data modified from the iris
dataset:
data <- structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5, 5.4, 4.6,
5, 4.4, 4.9, 5.4, 4.8), Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6,
3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4), Lon = c(-122.683, -122.688,
-122.686, -122.683, -122.678, -122.675, -122.674, -122.673, -122.676,
-122.674, -122.677, -122.68), Lat = c(45.523, 45.52, 45.514,
45.515, 45.513, 45.514, 45.517, 45.519, 45.519, 45.522, 45.524,
45.521)), class = "data.frame", .Names = c("Sepal.Length", "Sepal.Width",
"Lon", "Lat"), row.names = c(NA, -12L))
library(ggplot2)
library(igraph)
library(ggraph)
A simple plot of the positions of the coordinates looks like this:
ggplot(data, aes(x = Lon, y = Lat)) +
geom_point(size = 6)
layout
accepts a matrix so I'll extract here the coordinates and turn it into a matrix:
spatial_layout <- layout.norm(as.matrix(data[,c(3,4)]))
and then turn data
into a igraph object:
igraph_data <- graph_from_data_frame(data)
If I plot with the basic plot.igraph
the layout is as expected; the spatial coordinates of each point:
plot.igraph(igraph_data, layout = spatial_layout)
Now here is where I run into problems. I would rather use ggraph
to take advantage of the power of ggplot2
. However I am not sure how to get it to accept a spatial layout. This doesn't work:
ggraph(igraph_data, spatial_layout) +
geom_edge_link() +
geom_node_point(color = "black", size = 9, pch = 1) +
geom_node_text(aes(label = name))
Error in create_layout.igraph(graph, layout, ...) : Unknown layout
Nor does trying to create a custom layout:
create_layout(data, layout = "spatial_layout")
Error in create_layout.default(data, layout = "spatial_layout") :
No layout function defined for objects of class data.frame
Manually adding the lat/long data to the igraph object doesn't seem to do the trick either:
igraph_data$layout=cbind(E(igraph_data)$Lon,E(igraph_data)$Lat)
ggraph(igraph_data) +
geom_edge_link() +
geom_node_point(color = "black", size = 9, pch = 1) +
geom_node_text(aes(label = name))
Using
nicely
as default layout Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 12, 17
So ultimately my question is how do I add spatial data to a ggraph
layout? Obviously I am missing something here but I can't seem to figure out the right approach.
We can make the equivalent manual layout with ggraph::create_layout
. But first, we need to make the number of spatial coordinates match the number of vertexes in the graph we are passing. Looks like plot.igraph
was recycling your original layout silently.
# must have columns named x and y
data2 <- data.frame(x = rep(spatial_layout[,1], length.out = 17),
y = rep(spatial_layout[,2], length.out = 17))
Then use the help page for ?layout_igraph_manual
as a guide for subsequent argument names.
manual_layout <- create_layout(graph = igraph_data,
layout = "manual", node.positions = data2)
Note: I raise the warning Error: 'layout_igraph_manual' is not an exported object from 'namespace:ggraph'
when I call the function directly.
Then we can plug it into the original:
ggraph(manual_layout) +
geom_edge_link() +
geom_node_point(color = "black", size = 9, pch = 1) +
geom_node_text(aes(label = name))
The axis limits are not the same by default, but that's a small + xlim(-2.5,2.5)#ish
tweak.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With