Search code examples
rpurrrtidygraphr-futurefurrr

How to apply mapping functions using furrr on tidygraph objects?


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?


Solution

  • 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)