首页 > 解决方案 > 如何从 R 中的分组数据框中获取边列表(无向图)?

问题描述

我创建了一个网络,人们连接到特定事件(事件 1 的参与者连接到节点“event1”)。

我想知道是否可以删除节点“事件”并将参与该事件的人直接链接在一起。

我过去使用 Excel 处理原始数据做过类似的事情。我想知道是否有一种更快更好的方法可以在不离开 R 的情况下做到这一点。

数据集如下所示:

net1
from        to 
Person 1   Event1 
Person 2   Event1 
Person 3   Event2
Person 4   Event2 
Person 5   Event2 
Person 6   Event3
...

例如,我想删除“Event1”并将 Person1 和 Person2 连接在一起,因为我正在这样做。

如果我不能提供更好的代码来使用,我很抱歉。但是我不知道从哪里开始以这种方式操作。

标签: rnodesedgesnetwork-analysis

解决方案


我们可以使用tidyverse.

  1. group_split使用keep = FALSE参数将数据框按to列拆分为数据框列表,同时删除输出中的分组变量。

  2. map_dfr通过查找from和 自身的所有组合来扩展每个数据帧(如expand.grid)。_dfr意味着输出列表将被行绑定以形成一个数据框。

  3. pmap_dfr对数据帧的每一行进行操作,并水平排序(sort(c(...)))。set_names排序后需要对列进行排列。tibble(!!!将排序后的向量拼接成 的一行tibble,有效地将其转换为行向量。

  4. filterdistinct分别去除自环和重复链接。

请注意,group_splitgroup_map目前都是实验性功能。请谨慎使用。

library(tidyverse)

net1 %>%
  group_by(to) %>%
  group_split(keep = FALSE) %>%
  map_dfr(expand, crossing(from, to = from)) %>%
  pmap_dfr(~ tibble(!!!sort(c(...)) %>% set_names(c("from", "to")))) %>%
  filter(from != to) %>%
  distinct()

或与group_map

net1 %>%
  group_by(temp = to) %>%
  group_map(~ expand(.x, crossing(from, to = from))) %>%
  ungroup() %>%
  select(-temp) %>%
  pmap_dfr(~ tibble(!!!sort(c(...)) %>% set_names(c("from", "to")))) %>%
  filter(from != to) %>%
  distinct()

或与inner_join

net1 %>%
  inner_join(net1, by = "to") %>%
  select(from = from.x, to = from.y) %>%
  pmap_dfr(~ tibble(!!!sort(c(...)) %>% set_names(c("from", "to")))) %>%
  filter(from != to) %>%
  distinct()

我们也可以使用graph_from_data_framein 代替pmap_dfr来返回一个无向图(一定要在加载igraph 之前加载tidyverse,否则,你可能会得到一些意想不到的错误):

library(igraph)
library(tidyverse)

net1 %>%
  inner_join(net1, by = "to") %>%
  select(from = from.x, to = from.y) %>%
  igraph::graph_from_data_frame(directed = FALSE) %>%
  igraph::as_data_frame(what = "edges") %>%
  filter(from != to) %>%
  distinct()

输出:

# A tibble: 4 x 2
  from     to      
  <chr>    <chr>   
1 Person_1 Person_2
2 Person_3 Person_4
3 Person_3 Person_5
4 Person_4 Person_5

数据:

net1 <- structure(list(from = c("Person_1", "Person_2", "Person_3", "Person_4", 
"Person_5", "Person_6"), to = c("Event1", "Event1", "Event2", 
"Event2", "Event2", "Event3")), class = "data.frame", row.names = c(NA, 
-6L))

推荐阅读