如何从 R 中的分组数据框中获取边列表(无向图)?
How to get an edge list (undirected graph) from a grouped dataframe in R?
我创建了一个网络,人们可以在其中连接到特定事件(事件 1 的参与者连接到节点 "event1")。
我想知道是否可以删除节点 "event" 并直接 link 将参与该事件的人员聚集在一起。
我过去曾使用 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 连接在一起。
如果我不能提供更好的代码,我很抱歉。但是不知道从何入手才能这样操作
我们可以使用 tidyverse
来做到这一点。
group_split
和 keep = FALSE
参数将数据帧按 to
列拆分为数据帧列表,同时删除输出中的分组变量。
map_dfr
通过查找 from
和自身的所有组合(如 expand.grid
)来扩展每个数据帧。 _dfr
表示输出列表将row-bind组成dataframe
pmap_dfr
对数据帧的每一行进行操作,并水平排序 (sort(c(...))
)。需要 set_names
来排列排序后的列。 tibble(!!!
将排序后的向量拼接成 tibble
的一行,有效地将其变成行向量。
filter
和 distinct
分别删除 self-loops 和重复链接。
请注意,group_split
和 group_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_frame
代替pmap_dfr
到return一个无向图(一定要在[=74之前加载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))
我创建了一个网络,人们可以在其中连接到特定事件(事件 1 的参与者连接到节点 "event1")。
我想知道是否可以删除节点 "event" 并直接 link 将参与该事件的人员聚集在一起。
我过去曾使用 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 连接在一起。
如果我不能提供更好的代码,我很抱歉。但是不知道从何入手才能这样操作
我们可以使用 tidyverse
来做到这一点。
group_split
和keep = FALSE
参数将数据帧按to
列拆分为数据帧列表,同时删除输出中的分组变量。map_dfr
通过查找from
和自身的所有组合(如expand.grid
)来扩展每个数据帧。_dfr
表示输出列表将row-bind组成dataframepmap_dfr
对数据帧的每一行进行操作,并水平排序 (sort(c(...))
)。需要set_names
来排列排序后的列。tibble(!!!
将排序后的向量拼接成tibble
的一行,有效地将其变成行向量。filter
和distinct
分别删除 self-loops 和重复链接。
请注意,group_split
和 group_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_frame
代替pmap_dfr
到return一个无向图(一定要在[=74之前加载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))