将有向从属矩阵转换为边列表

convert directed affiliation matrix to edge list

我有一个定向从属关系矩阵,我想将其转换为边列表。矩阵如下所示:

State   WarID    Initiator
A        1       1
B        1       0
A        2       1
C        2       0
D        2       0
B        3       1
C        3       1
D        3       0

其中“State”是国家名称,“WarID”是 war 的唯一标识符,“Initiator”是虚拟变量,如果国家发起 war.如果两个状态共享相同的“WarID”但具有不同的“Initiator”值,则它们之间存在边缘。

我想把上面的从属关系矩阵改成这样的边列表:

Initiator   Target  WarID
A              B    1
A              C    2
A              D    2
B              D    3
C              D    3

我知道如何将基本的从属关系矩阵更改为边列表,但我在保留“定向网络”组件方面遇到了困难。如果有人能告诉我如何在 R 中有效地执行此操作,我将不胜感激(我有一个非常大的隶属关系矩阵)。

这个有用吗:

> library(dplyr)
> df %>% group_by(WarID) %>% filter(Initiator == 1) %>% 
+   inner_join(df %>% group_by(WarID) %>% filter(Initiator == 0), by = ('WarID')) %>% rename(Target = State.y, Initiator = State.x ) %>% 
+   select(1,4,2)
# A tibble: 5 x 3
# Groups:   WarID [3]
  Initiator Target WarID
  <chr>     <chr>  <dbl>
1 A         B          1
2 A         C          2
3 A         D          2
4 B         D          3
5 C         D          3
> 

使用的数据:

> dput(df)
structure(list(State = c("A", "B", "A", "C", "D", "B", "C", "D"
), WarID = c(1, 1, 2, 2, 2, 3, 3, 3), Initiator = c(1, 0, 1, 
0, 0, 1, 1, 0)), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -8L), spec = structure(list(cols = list(
    State = structure(list(), class = c("collector_character", 
    "collector")), WarID = structure(list(), class = c("collector_double", 
    "collector")), Initiator = structure(list(), class = c("collector_double", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
"collector")), skip = 1), class = "col_spec"))
> 

使用 tidyverse 你可以做:

library(tidyverse)
df %>%
   group_by(WarID) %>%
   summarise(Target = list(State[Initiator==0]),
             Initiator = list(State[Initiator==1]), .groups='drop') %>% 
   unnest(c(Initiator, Target)) %>%
   rev() # Just to reverse the ordering, otherwise not necessary 

    # A tibble: 5 x 3
  Initiator Target WarID
  <chr>     <chr>  <int>
1 A         B          1
2 A         C          2
3 A         D          2
4 B         D          3
5 C         D          3

您可以使用 tapplyWarIDInitiator 对数据进行分组,并为每个 WarID 创建一个 expand.grid。只是 rbind 结果。

FUN <- function(d) {
  r <- with(d, tapply(State, list(WarID, Initiator), I))
  r <- lapply(1:nrow(r), function(i) cbind(expand.grid(rev(r[i, ])), i))
  r <- setNames(do.call(rbind, r), c("Initiator", "Target", "WarID"))
  r
}
FUN(d)
#   Initiator Target WarID
# 1         A      B     1
# 2         A      C     2
# 3         A      D     2
# 4         B      D     3
# 5         C      D     3

请注意,我使用了您指定的连续 WarIDs。


数据:

d <- structure(list(State = c("A", "B", "A", "C", "D", "B", "C", "D"
), WarID = c(1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), Initiator = c(1L, 
0L, 1L, 0L, 0L, 1L, 1L, 0L)), class = "data.frame", row.names = c(NA, 
-8L))