my problem is the following. I have a network with multiple layers (based on edge attributes), like year
in the highschool
network.
I would like to store node degree for each layer as a separate node attribute, to use it in visualisation.
While facet_edges
is a great and easy way of showing state-specific interaction differences (i.e. the interactions in 1957 and 1958 in case of the highschool
network), when you want to highlight the consequence of these interaction differences, for example the degree, it naturally does not get re-calculated for the subgraphs.
gr <- as_tbl_graph(highschool)
gr <- gr |> mutate(d = centrality_degree())
ggraph(gr, layout = "stress") +
geom_edge_link() +
geom_node_point(aes(size = d)) +
facet_edges(~year)
This is related to this question Small multiples plots replicating entire network in each panel in ggraph() / this issue https://github.com/thomasp85/ggraph/issues/343, as goal is to visualise the changes like so (feat1 and feat2 are not the degree of course, but might as well be):
gr <- as_tbl_graph(highschool) |>
mutate(
feat1 = sample(1:3, n(), replace = TRUE),
feat2 = sample(1:8, n(), replace = TRUE)
) |>
mutate_at(vars(feat1, feat2), as.factor)
p1 <- ggraph(gr) +
geom_edge_link(alpha = 0.1) +
geom_node_point(aes(size = feat1)) +
scale_color_brewer(type = "qual") +
theme_graph()
#> Using "stress" as default layout
p2 <- ggraph(gr) +
geom_edge_link(alpha = 0.1) +
geom_node_point(aes(size = feat2)) +
scale_color_brewer(type = "qual") +
theme_graph()
#> Using "stress" as default layout
p1 + p2
I have not found a good way to do this yet. One way to do this is to split the layers apart into separate networks and visualise them separately, but in that case the node positions will not be mapped, and it becomes more difficult to compare the networks.
I attempted to calculate the degree for each layer separately by morphing it, but I'm stuck.
gr |> activate(edges) |> morph(to_split,year) |> crystallise()
Splitting by edges
# A tibble: 2 × 2
name graph
<chr> <list>
1 year: 1957 <tbl_grph>
2 year: 1958 <tbl_grph>
My plan was to calculate the degree with mutate
for each subgraph in the graph
column above, and then save them as separate node columns for each layer using pivot_wider
. This would (in theory) replicate the feat1
and feat2
columns in the example above
gr |>
activate(edges) |>
morph(to_split,year) |>
activate(nodes) |>
mutate(d = centrality_degree()) |>
crystallise()
However, I'm getting the following error:
Splitting by edges
Error in `private$check()`:
! This function should not be called directly
Has anyone encountered this before? Does anyone have a better idea to solve this?
You're so close, you need to unmorph()
, then activate()
edges, then morph()
and crystallise()
see the reprex below:
suppressPackageStartupMessages({
library(dplyr)
library(ggplot2)
library(ggraph)
library(tidygraph)
})
gr <- as_tbl_graph(highschool) |>
mutate(
feat1 = sample(1:3, n(), replace = TRUE),
feat2 = sample(1:8, n(), replace = TRUE)
) |>
mutate_at(vars(feat1, feat2), as.factor)
gr |>
activate(edges) |>
morph(to_split, year) |>
activate(nodes) |>
mutate(deg = centrality_degree()) |>
unmorph() |>
activate(edges) |>
morph(to_split, year) |>
crystallise()
#> Splitting by edges
#> Splitting by edges
#> # A tibble: 2 × 2
#> name graph
#> <chr> <list>
#> 1 year: 1957 <tbl_grph>
#> 2 year: 1958 <tbl_grph>
Created on 2023-08-16 with reprex v2.0.2
To extract metrics you could use purrr::map()
to iterate over the graph
column.