根据应用于两条边的条件创建二分投影

Create bipartite projection based on condition applied to two edges

提问人:markrt 提问时间:11/11/2023 最后编辑:ThomasIsCodingmarkrt 更新时间:11/15/2023 访问量:46

问:

我有一个具有不同源节点和目标节点的数据集,以及一个与关系相关的数值变量。

它看起来有点像这样:

library(igraph)
library(tidygraph)

set.seed(24601)

example_data <- 
  data.frame(source = 
             sample(letters[1:10],
                    100,
                    replace = TRUE),
           target =
             sample(letters[16:25],
                    100,
                    replace = TRUE),
           important_variable =
             rnorm(100))

想象一下,source 的成员是个人,target 的成员是他们去过的不同城市,我想创建一个网络来显示同一个人访问两个给定城市的时间。我会为此使用 bipartite_projection(),如下所示:


example_data %>% 
  graph_from_data_frame() %>% 
  as_tbl_graph() %>% 
  mutate(type = 
           ifelse(name %in% letters[1:10],
                   TRUE,
                   FALSE)) %>% 
  bipartite_projection(which = "true")

但是,我只想在满足特定条件时连接不同的城市:例如,当important_variable值的差异最大为 0.5 时(例如,当同一个人在同一年访问了两个城市时,我对此感兴趣)。目前,使用bipartite_projection后,来自important_variable的信息将被丢弃。

我看不到基于第三个数值变量限制bipartite_projection的方法。可以这样做吗?提前感谢您的任何帮助。

使用编辑进行更新以显示所需的输出:

让我们看一小部分行:

example_data %>% 
  filter(source == "a") %>% 
  head()

这将产生以下结果:

  source target important_variable
1      a      x         0.29773720
2      a      p         1.50474490
3      a      y         0.01149263
4      a      q         0.19391773
5      a      t        -0.10656946
6      a      w        -0.29516668

我可以直接进入二分投影,如下所示:

example_data %>% 
  filter(source == "a") %>% 
  head()  %>% 
  graph_from_data_frame() %>% 
  as_tbl_graph() %>% 
  mutate(type = 
           ifelse(name %in% letters[1:10],
                  TRUE,
                  FALSE)) %>% 
  bipartite_projection(which = "false")

它生成一个具有一个顶点属性 - - 和一个边属性 - 的 iGraph 对象。namenode

但是,我想要看起来像这样的东西(为简单起见,只有前四行):

  source_projected target_projected source_att  target_att
1                x                p  0.2977372  1.50474490
2                x                y  0.2977372  0.01149263
3                x                q  0.2977372  0.19391773
4                x                t  0.2977372 -0.10656946

因为这将允许我根据 my 和列之间的关系进行过滤(例如,过滤 and 之间的差值小于 0.5)source_atttarget_attsource_atttarget_att

第二次更新,具有更详细的所需输出

@ThomasIsCoding提供了一个符合我要求的解决方案。这让我意识到我不够详细。

从原始数据重新开始,我们可以看到它被链接到两次,并且被链接到两次。在每种情况下,的值都不同。见下文:apayimportant_variable

example_data %>% 
  filter(source == "a" &
           (target == "p" |
              target == "y")) 

  source target important_variable
1      a      p         1.50474490
2      a      y         0.01149263
3      a      y        -2.34069094
4      a      p         0.29294049

我发布的示例所需数据仅包括连接一次的每个节点。但是,由于 的值不同,我希望包含这些配对的所有配置的输出如下所示:targetimportant_variable

  source_projected target_projected source_att  target_att
1                p                y  0.2977372  0.01149263
2                p                y  0.2977372 -2.34069094
3                p                y  0.2929405  0.01149263
4                p                y  0.2929405 -2.34069094

这是可以建造的吗?谢谢!

R igraph bipartite tidygraph

评论

0赞 ThomasIsCoding 11/13/2023
请显示所需的输出作为示例
0赞 markrt 11/13/2023
@ThomasIsCoding完成了!谢谢你的评论。

答:

0赞 ThomasIsCoding 11/13/2023 #1

更新

由于单个目标可能有多个值,因此我想最好使用并启用参数left_join"many-to-many"relationship

out <- example_data %>%
    graph_from_data_frame() %>%
    set_vertex_attr(
        name = "type",
        value = names(V(.)) %in% example_data$target
    ) %>%
    bipartite_projection() %>%
    pluck("proj2") %>%
    as_data_frame() %>%
    select(-weight) %>%
    left_join(select(example_data, -source),
        join_by(from == target),
        relationship = "many-to-many"
    ) %>%
    left_join(select(example_data, -source),
        join_by(to == target),
        relationship = "many-to-many"
    ) %>%
    rename(all_of(c(source_att = "important_variable.x", target_att = "important_variable.y")))

你会看到

> head(out)
  from to source_att  target_att
1    x  y  0.2977372  0.50506407
2    x  y  0.2977372 -1.37333412
3    x  y  0.2977372  0.61981223
4    x  y  0.2977372  0.43724194
5    x  y  0.2977372 -1.97363488
6    x  y  0.2977372 -0.02413137

> glimpse(out)
Rows: 4,462
Columns: 4
$ from       <chr> "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x",…
$ to         <chr> "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y",…
$ source_att <dbl> 0.2977372, 0.2977372, 0.2977372, 0.2977372, 0.2977372, 0.29…
$ target_att <dbl> 0.50506407, -1.37333412, 0.61981223, 0.43724194, -1.9736348…

以前

也许你可以试试下面的代码

example_data %>%
    graph_from_data_frame() %>%
    set_vertex_attr(
        name = "type",
        value = names(V(.)) %in% example_data$target
    ) %>%
    bipartite_projection() %>%
    pluck("proj2") %>%
    as_data_frame() %>%
    select(-weight) %>%
    mutate(
        source_att = with(example_data, important_variable[match(from, target)]),
        target_att = with(example_data, important_variable[match(to, target)])
    )

这给了

   from to  source_att  target_att
1     x  y  0.29773720  0.50506407
2     x  p  0.29773720 -0.74022203
3     x  u  0.29773720 -2.04969760
4     x  q  0.29773720  1.36281039
5     x  w  0.29773720 -0.47578690
6     x  s  0.29773720  0.03233063
7     x  t  0.29773720 -1.08378137
8     x  r  0.29773720 -0.72029435
9     x  v  0.29773720 -0.22919308
10    y  p  0.50506407 -0.74022203
11    y  u  0.50506407 -2.04969760
12    y  q  0.50506407  1.36281039
13    y  w  0.50506407 -0.47578690
14    y  s  0.50506407  0.03233063
15    y  t  0.50506407 -1.08378137
16    y  r  0.50506407 -0.72029435
17    y  v  0.50506407 -0.22919308
18    p  u -0.74022203 -2.04969760
19    p  q -0.74022203  1.36281039
20    p  w -0.74022203 -0.47578690
21    p  s -0.74022203  0.03233063
22    p  t -0.74022203 -1.08378137
23    p  r -0.74022203 -0.72029435
24    p  v -0.74022203 -0.22919308
25    r  u -0.72029435 -2.04969760
26    r  q -0.72029435  1.36281039
27    r  w -0.72029435 -0.47578690
28    r  s -0.72029435  0.03233063
29    r  t -0.72029435 -1.08378137
30    r  v -0.72029435 -0.22919308
31    u  q -2.04969760  1.36281039
32    u  w -2.04969760 -0.47578690
33    u  s -2.04969760  0.03233063
34    u  t -2.04969760 -1.08378137
35    u  v -2.04969760 -0.22919308
36    v  s -0.22919308  0.03233063
37    v  t -0.22919308 -1.08378137
38    v  q -0.22919308  1.36281039
39    v  w -0.22919308 -0.47578690
40    q  w  1.36281039 -0.47578690
41    q  s  1.36281039  0.03233063
42    q  t  1.36281039 -1.08378137
43    w  s -0.47578690  0.03233063
44    w  t -0.47578690 -1.08378137
45    s  t  0.03233063 -1.08378137

然后我想你知道如何在约束 和 之间的差异的情况下过滤行。source_atttarget_att

评论

0赞 markrt 11/13/2023
这是一个很大的帮助,谢谢。我已经更新了我的问题以澄清我正在寻找的输出 - 有几种不同的配置,所以我想要一些保留它们的东西,而不是将它们组合成一行,并使用bipartite_proejction的权重变量。很抱歉,我最初呈现的所需输出没有包含此细节。
0赞 ThomasIsCoding 11/13/2023
@markrt我知道这一点,但不确定您是否打算进行多对多映射。现在请看我的更新。
0赞 markrt 11/13/2023
了不起!谢谢。