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

问题描述

我有一个直接从属关系矩阵,我想将其转换为边缘列表。矩阵如下:

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

其中“州”是国家/地区的名称,“ WarID”是战争的唯一标识符,而“发起者”是一个虚拟变量,如果州发起战争,则该变量等于1。如果两个州共享相同的“ WarID”,但“ Initiator”的值不同,则这两个州之间会有一条边缘。

我想将上面的隶属关系矩阵更改为这样的边列表:

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

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

解决方法

您可以使用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
,

这项工作:

> 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","D"
),WarID = c(1,1,2,3,3),Initiator = c(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",Initiator = structure(list(),"collector"))),default = structure(list(),class = c("collector_guess",skip = 1),class = "col_spec"))
> 
,

您可以使用WarID将数据按Initiatortapply分组,并为每个expand.grid制作一个WarID。只需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

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


数据:

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...