The parallel calculations on tidygraph centrality functions using furrr is throwing an error:
"Error in mutate_impl(.data, dots) : Evaluation error: This function should not be called directly."
Here is my code:
library(tidyverse)
library(tidygraph)
library(furrr)
H <- play_islands(5, 10, 0.8, 3)
cent <- tribble(
~f, ~params,
"centrality_degree", list(H),
"centrality_authority", list(H)
)
cent %>%
mutate(centrality = future_invoke_map(f, params, .options = future_options(packages = c("tidygraph", "tidyverse"))))
How should I fix this?
I believe you have a misunderstanding about how the tidygraph works, which prevents you from coding this correctly.
The functions centrality_degree()
and centrality_authority()
are both used within a mutate()
statement (see https://tidygraph.data-imaginist.com/reference/centrality.html).
library(tidygraph)
#> Attaching package: 'tidygraph'
#> The following object is masked from 'package:stats':
#>
#> filter
create_notable('bull') %>%
activate(nodes) %>%
mutate(importance = centrality_authority())
#> # A tbl_graph: 5 nodes and 5 edges
#> #
#> # An undirected simple graph with 1 component
#> #
#> # Node Data: 5 x 1 (active)
#> importance
#> <dbl>
#> 1 0.869
#> 2 1
#> 3 1
#> 4 0.434
#> 5 0.434
#> #
#> # Edge Data: 5 x 2
#> from to
#> <int> <int>
#> 1 1 2
#> 2 1 3
#> 3 2 3
#> # ... with 2 more rows
Created on 2020-07-03 by the reprex package (v0.3.0)
Note that centrality_authority()
function within the mutate()
statement. In other words, you'll need to wrap these functions around another function to pass to the furrr
functions.
Also, note that the result of the proper use of these functions return a tidygraph
object. There is a function graph_join()
that allows us to join multiple graphs together. So a plan similar to the one you have proposed is to calculate separate centrality measures, which each return a graph object, and then to join them together with graph_join()
.
With this knowledge, we can code this up as follows (note a minor change to your code where we have to add some unique ID name to the nodes so that we can join the graphs together).
# Load libraries
library(tidyverse)
library(tidygraph)
#> Attaching package: 'tidygraph'
#> The following object is masked from 'package:stats':
#>
#> filter
library(furrr)
#> Loading required package: future
# Create example graph
H <- play_islands(5, 10, 0.8, 3) %>%
mutate(name = 1:50) # Add node names to join
# Create functions to add centrality measures
f_c_deg <- function(x) x %>% mutate(c_deg = centrality_degree())
f_c_aut <- function(x) x %>% mutate(c_aut = centrality_authority())
# Setup mapping data frame
cent <- tribble(
~f, ~params,
"f_c_deg", list(x = H),
"f_c_aut", list(x = H)
)
# Apply functions and join
res <- future_invoke_map(cent$f, cent$params)
one_g <- Reduce(graph_join, res) # Put together results and view single graph
#> Joining, by = "name"
one_g
#> # A tbl_graph: 50 nodes and 416 edges
#> #
#> # A directed acyclic multigraph with 1 component
#> #
#> # Node Data: 50 x 3 (active)
#> name c_deg c_aut
#> <int> <dbl> <dbl>
#> 1 1 7 0.523
#> 2 2 9 0.661
#> 3 3 9 0.670
#> 4 4 8 0.601
#> 5 5 9 0.637
#> 6 6 11 0.823
#> # ... with 44 more rows
#> #
#> # Edge Data: 416 x 2
#> from to
#> <int> <int>
#> 1 1 2
#> 2 1 3
#> 3 1 4
#> # ... with 413 more rows
Created on 2020-07-03 by the reprex package (v0.3.0)