为来自 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 <--
使用以下数据。您可以使用 apply
和 combn
实现您的目标。此 return 是一个列表矩阵,其中包含 data.frame
的行元素的成对比较
myPairs <- apply(t(dat), 2, function(x) t(combn(x[!is.na(x)], 2)))
请注意,apply 的输出可能很挑剔,这里必须至少有一行带有 NA,这样 apply
将 return 是一个列表而不是矩阵。
如果你想要一个 data.frame 最后,使用 do.call
和 rbind
将矩阵放在一起,然后 data.frame
和 setNames
对象强制和添加名称。
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))
我正在尝试在 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 <--
使用以下数据。您可以使用 apply
和 combn
实现您的目标。此 return 是一个列表矩阵,其中包含 data.frame
myPairs <- apply(t(dat), 2, function(x) t(combn(x[!is.na(x)], 2)))
请注意,apply 的输出可能很挑剔,这里必须至少有一行带有 NA,这样 apply
将 return 是一个列表而不是矩阵。
如果你想要一个 data.frame 最后,使用 do.call
和 rbind
将矩阵放在一起,然后 data.frame
和 setNames
对象强制和添加名称。
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))