为data.frame

时间:2017-08-17 18:22:25

标签: r dataframe igraph reshape reshape2

我正在尝试在igraph中进行网络分析,但考虑到不同的列数,我在将数据集转换为边缘列表(带权重)方面存在一些问题。

数据集如下所示(df1)(当然要大得多):首先是主操作符id(主操作符也可以是伙伴,反之亦然,因此ID在边缘保持不变列表)挑战是合作伙伴的数量不同(从0到40)并且必须考虑每个互动(不仅仅是#34; IdMain到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
.
.

我已经获得了有用的提示,可以使用reshape来执行此操作,例如:

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

然而,这只会创造一个“定向”的对象。 edgelist(从Main到Partners)。我需要的是下面的内容,其中记录了每次互动。

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

有没有人提示最好的方法是什么?我也查看了igraph库,但无法找到执行此操作的函数。

2 个答案:

答案 0 :(得分:1)

不需要重塑(2)和熔化等。您只需要抓取每个列对的组合,然后将它们绑定在一起。

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 <--

答案 1 :(得分:1)

使用以下数据。您可以使用applycombn来实现您的目标。这将返回一个列表矩阵,其中包含data.frame

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

请注意,apply的输出可能很挑剔,此处必须至少有一行带有NA,以便apply返回列表而不是矩阵。

如果您想在最后使用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))