在 tidygraph 中过滤

filter in a tidygraph

考虑这个简单的例子

library(tidygraph)

mynodes <- tibble(id = c(1,2,3,4,5))

myedges <- tibble(from = c(1,1,1,5),
                  to = c(1,2,3,4),
                  power = c(10,10,10,3))

tbl_graph(nodes = mynodes, edges = myedges)
# A tbl_graph: 5 nodes and 4 edges
#
# A directed multigraph with 2 components
#
# Node Data: 5 x 1 (active)
     id
  <dbl>
1     1
2     2
3     3
4     4
5     5
#
# Edge Data: 4 x 3
   from    to power
  <int> <int> <dbl>
1     1     1    10
2     1     2    10
3     1     3    10
# ? with 1 more row

我知道我可以使用 filter 轻松过滤节点或边。

我的问题是如何根据边上的条件过滤节点。

例如运行:

mygraph %>% activate(edges) %>% filter(power == 3)

仍然 returns 所有 节点,这在绘图时很烦人(这些节点将没有边!)。

如何保留与我过滤的边集连接的所有节点?

# A tbl_graph: 5 nodes and 1 edges
#
# A rooted forest with 4 trees
#
# Edge Data: 1 x 3 (active)
   from    to power
  <int> <int> <dbl>
1     5     4     3
#
# Node Data: 5 x 1
     id
  <dbl>
1     1
2     2
3     3
# ? with 2 more rows

一种可能的解决方案是将您的数据转换为 subgraph 并按 id:

过滤

通过 id 创建 subgraphfilter:

sub_mygraph <- to_subgraph(mygraph, id %in% c(4, 5), subset_by = "nodes")$subgraph 

sub_mygraph
# A tbl_graph: 2 nodes and 1 edges
#
# A rooted tree
#
# Node Data: 2 x 1 (active)
     id
  <dbl>
1     4
2     5
#
# Edge Data: 1 x 3
   from    to power
  <int> <int> <dbl>
1     2     1     3

或者您可以将数据转换为 data.frame 并通过 power 过滤,然后再转换为 tbl_graph

转换为data.frame:

library(tidygraph)

mygraph %>% igraph::as_data_frame() %>% 
  filter(power == 3) %>% 
  as_tbl_graph()

# A tbl_graph: 2 nodes and 1 edges
#
# A rooted tree
#
# Node Data: 2 x 1 (active)
  name 
  <chr>
1 5    
2 4    
#
# Edge Data: 1 x 3
   from    to power
  <int> <int> <dbl>
1     1     2     3

或者您可以按 id 进行筛选,但这不是最直接的方法,因为您首先必须确定 power 中包含的 id 3:

mygraph %>% filter(id %in% c(5, 4))

# A tbl_graph: 2 nodes and 1 edges
#
# A rooted tree
#
# Node Data: 2 x 1 (active)
     id
  <dbl>
1     4
2     5
#
# Edge Data: 1 x 3
   from    to power
  <int> <int> <dbl>
1     2     1     3

现在您可以在没有烦人的节点的情况下绘制它了:

library(ggraph)

mygraph %>% igraph::as_data_frame() %>% 
  filter(power == 3) %>% 
  as_tbl_graph () %>% 
  rename(id = name) %>% 
  ggraph() +
  geom_edge_fan() +
  geom_node_point(aes(color = id)) +
  theme_graph()

备注

请注意,转换为 data.frame 将更改您的 id 变量名称,因此您可以使用 rename 再次更改它。

其实有一个很简单的解决方法

activate(nodes) %>% 
  filter(!node_is_isolated())

您可以使用 .E() 和 .N() fcns 访问节点或边,而另一个在 tidygraph 中被激活

这里的介绍中提到了这一点: https://www.data-imaginist.com/2017/introducing-tidygraph/

因此,要根据边属性过滤到节点,您可以在激活节点时使用 .E() 函数:

mygraph %>%
  activate("nodes") %>%
  filter(.E()$power[id] == 3)