4

I'm having some trouble groking certain Tidygraph operations that are relatively straightforward in igraph.

In particular I would like to analyze specific neighborhoods at different orders. I think I need to use Morphs for this, but I just haven't got it working.

library(tidygraph)
library(ggraph)
net <- tibble::tibble(A = letters[1:6],
               B = rep(c("x", "y"), each = 3)) %>% 
  tidygraph::as_tbl_graph()

For example, say I have the following network structure:

I want to analyze the neighborhood about x.

net %>% 
  ggraph(layout = "nicely") +
    geom_edge_link() +
    geom_node_point(size = 10, fill = "white", shape = 21) +
    geom_node_text(aes(label = name)) +
    theme_graph()

Full network

The iGraph implementation works as follows:

Extract the neighborhood of node x.

v <- net %>% 
  tidygraph::as.igraph() %>% 
  igraph::neighborhood(nodes = "x", order = 1)

build a subgraph by unlisting the igraph.vs object

igraph::induced_subgraph(net, vids = unlist(v)) %>% 
  tidygraph::as_tbl_graph() %>% 
  ggraph(layout = "nicely") +
    geom_edge_link() +
    geom_node_point(size = 10, fill = "white", shape = 21) +
    geom_node_text(aes(label = name)) +
    theme_graph()

desired neighborhood

How do I do this with tidygraph?

The following implementations return the same error:

net %>% 
  tidygraph::morph(to_local_neighborhood, node = "x", order = 1, mode = "all")

net %>% 
  to_local_neighborhood(node = "x", order = 1, mode = "all")
Error in if (is.numeric(v) && any(v < 0)) { : missing value where TRUE/FALSE needed
user131291
  • 147
  • 6
  • 1
    It seems that instead of giving the node by its name, you have to give it by position. In your example, node x is number 7. I'm currently not finding a better way of doing that than filtering the nodes, pulling out that position, and using that to get a subgraph. You could also use the `dplyr`-type function `filter` with `node_is_adjacent` – camille Aug 15 '19 at 21:31
  • @camille That's unfortunate. While `node_is_adjacent` would work for this use case (although I haven't tested yet). It seems that this solution wouldn't work for orders greater than 1 (ie to get neighbor's neighbors, for example). – user131291 Aug 15 '19 at 22:42
  • 1
    Yeah there might be a better way, not sure. Why not just use the `igraph` functions? It seems easy enough to switch between `tidygraph` classes and `igraph` ones – camille Aug 16 '19 at 01:32
  • In case anyone finds this in the future, refer to [this github issue](https://github.com/thomasp85/tidygraph/issues/98#issuecomment-542386203) for more details on a solution. I will try to post a final solution later. – user131291 May 11 '20 at 15:04

1 Answers1

3

A little more roundabout using some base R functions than the GitHub-linked solution in case you're not as familiar with the tidygraph API, but we can get the index of the node using @camille's insight for requiring the node parameter to be a number.

library(tidygraph)
#> Attaching package: 'tidygraph'
#> The following object is masked from 'package:stats':
#> 
#>     filter
library(ggraph)
#> Loading required package: ggplot2

# Example
net <- tibble::tibble(A = letters[1:6],
                      B = rep(c("x", "y"), each = 3)) %>% 
  tidygraph::as_tbl_graph()

# Get row name index as integer because tidygraph requirement
node_tbl <- data.frame(activate(net, nodes))  # Make sure focus on nodes
node_idx <- rownames(node_tbl)[node_tbl$name == "x"]
node_idx <- as.integer(node_idx)  # tidygraph needs it as number, not string

net %>%
  tidygraph::convert(to_local_neighborhood,
                     node = node_idx,
                     order = 1,
                     mode = "all") %>%
  ggraph(layout = "nicely") +
  geom_edge_link() +
  geom_node_point(size = 10, fill = "white", shape = 21) +
  geom_node_text(aes(label = name)) +
  theme_graph()

Created on 2020-07-03 by the reprex package (v0.3.0)

And here's the GitHub-linked solution which takes advantage of tidygraph's API more by using the .N() in the conversion to reference the node table in which(.N()$name == "x").

library(tidygraph)
#> Attaching package: 'tidygraph'
#> The following object is masked from 'package:stats':
#> 
#>     filter
library(ggraph)
#> Loading required package: ggplot2

# Example
net <- tibble::tibble(A = letters[1:6],
                      B = rep(c("x", "y"), each = 3)) %>% 
  tidygraph::as_tbl_graph()

net %>%
  tidygraph::convert(to_local_neighborhood,
                     node = which(.N()$name == "x"),
                     order = 1,
                     mode = "all") %>%
  ggraph(layout = "nicely") +
  geom_edge_link() +
  geom_node_point(size = 10, fill = "white", shape = 21) +
  geom_node_text(aes(label = name)) +
  theme_graph()

Created on 2020-07-03 by the reprex package (v0.3.0)

Eric Leung
  • 2,354
  • 12
  • 25