为来自 data.frame 的所有交互创建边缘列表

Create edgelist for all interactions from data.frame

我正在尝试在 igraph 中进行网络分析,但是在将我拥有的数据集转换为边缘列表(具有权重)时遇到了一些问题,因为列数不同。

数据集如下所示(df1)(当然要大得多):首先是主要运营商id(主要运营商也可以是合作伙伴,反之亦然,所以Ids保持不变边缘列表)挑战在于合作伙伴的数量各不相同(从 0 到 40)并且必须考虑每次互动(不仅仅是 "IdMain to IdPartnerX")。

IdMain IdPartner1  IdPartner2  IdPartner3 IdPartner4 .....
1      4           3           7          6
2      3           1          NA          NA
3      1           4           2          NA
4      9           6           3          NA
.
.

我已经得到了使用重塑来执行此操作的有用提示,例如:

data_melt <- reshape2::melt(data, id.vars = "IdMain")
edgelist <- data_melt[!is.na(data_melt$value), c("IdMain", "value")]

但是,这只会创建一个 'directed' 边缘列表(从 Main 到 Partners)。我需要的是如下所示的内容,其中记录了每次交互。

Id1 Id2 
1   4    
1   3    
1   7    
1   6        
4   3
4   7
4   6
3   7
etc

有没有人知道最好的路线是什么?我还查看了 igraph 库,但找不到执行此操作的函数。

不需要reshape(2) 和 melting 等。你只需要抓住每个列对的组合,然后将它们绑定在一起。

x <- read.table(text="IdMain IdPartner1  IdPartner2  IdPartner3 IdPartner4
1      4           3           7          6
2      3           1          NA          NA
3      1           4           2          NA
4      9           6           3          NA", header=TRUE)

idx <- t(combn(seq_along(x), 2))
edgelist <- lapply(1:nrow(idx), function(i) x[, c(idx[i, 1], idx[i, 2])])
edgelist <- lapply(edgelist, setNames, c("ID1","ID2"))
edgelist <- do.call(rbind, edgelist)
edgelist <- edgelist[rowSums(is.na(edgelist))==0, ]
edgelist
#    ID1 ID2
# 1    1   4
# 2    2   3
# 3    3   1
# 4    4   9
# 5    1   3
# 6    2   1
# 7    3   4
# 8    4   6
# 9    1   7
# 11   3   2
# 12   4   3
# 13   1   6
# 17   4   3
# 18   3   1
# 19   1   4
# 20   9   6
# 21   4   7
# 23   1   2
# 24   9   3
# 25   4   6
# 29   3   7 <--
# 31   4   2
# 32   6   3
# 33   3   6 <--
# 37   7   6 <--

使用以下数据。您可以使用 applycombn 实现您的目标。此 return 是一个列表矩阵,其中包含 data.frame

的行元素的成对比较
 myPairs <- apply(t(dat), 2, function(x) t(combn(x[!is.na(x)], 2)))

请注意,apply 的输出可能很挑剔,这里必须至少有一行带有 NA,这样 apply 将 return 是一个列表而不是矩阵。

如果你想要一个 data.frame 最后,使用 do.callrbind 将矩阵放在一起,然后 data.framesetNames对象强制和添加名称。

setNames(data.frame(do.call(rbind, myPairs)), c("Id1", "Id2"))
   Id1 Id2
1    1   4
2    1   3
3    1   7
4    1   6
5    4   3
6    4   7
7    4   6
8    3   7
9    3   6
10   7   6
11   2   3
12   2   1
13   3   1
14   3   1
15   3   4
16   3   2
17   1   4
18   1   2
19   4   2
20   4   9
21   4   6
22   4   3
23   9   6
24   9   3
25   6   3

数据

dat <- 
structure(list(IdMain = 1:4, IdPartner1 = c(4L, 3L, 1L, 9L), 
    IdPartner2 = c(3L, 1L, 4L, 6L), IdPartner3 = c(7L, NA, 2L, 
    3L), IdPartner4 = c(6L, NA, NA, NA)), .Names = c("IdMain", 
"IdPartner1", "IdPartner2", "IdPartner3", "IdPartner4"),
class = "data.frame", row.names = c(NA, -4L))