如何从R中的数据构造边缘列表?

时间:2016-08-08 12:14:37

标签: r

我有一些看起来像这样的数据:

+--------+-----------+
| Source |  Targets  |
+--------+-----------+
|      1 |   3, 4, 5 |
|      2 |      1, 3 |
|      3 | 6, 10, 11 |
+--------+-----------+

其中source是图数据中的节点,然后Targets是目标节点的列表,即从节点1到3,4的连接, d 5个节点。我想创建一个边列表,如下所示:

+------+----+
| From | To |
+------+----+
|    1 |  3 |
|    1 |  4 |
|    1 |  5 |
+------+----+

但我无法在R中完成这项工作。我能做的最好的事情如下:

extract_edges <- function(row) {
  targets <- strsplit(as.character(locke_relations[row, 3]), ", ")
  df <- data.frame()
  for(t in targets) {
    newrow <- data.frame(from=locke_relations[row,1], to=t)
    df <- rbind(df, newrow)
  }
  df
}
lapply((2:3), extract_edges)
上面的

locke_relations是上面表格中或多或少的数据,在上面的代码中,我只处理两行(第2行和第3行)。它为我提供了一个包含或多或少正确的数据框的列表:

[[1]]
   from    to
1 47678 48378
2 47678 48379

[[2]]
   from    to
1 47686 47804
2 47686 49326

但我真正想要的是:

   from    to
1 47678 48378
2 47678 48379
3 47686 47804
4 47686 49326

我可以尝试找到一种方法将列表合并在一起,但我觉得我的整个方法都是关闭的,而在R中有一种更有效的方法来实现这一点。有谁知道在R中这样做的最佳方法是什么?

2 个答案:

答案 0 :(得分:3)

您可以使用separate_rows中的tidyr

tidyr::separate_rows(df, Targets)

#  source target
#1      1      3
#2      1      4
#3      1      5
#4      2      1
#5      2      3
#6      3      6
#7      3     10
#8      3     11

答案 1 :(得分:1)

我会打赌data.table(我99%肯定会最快,效率最高):

library(data.table)
data = "1 2,3,4\n2 3,4,5"
dt = fread(data, sep = " ", col.names = c("from", "to"))
res = dt[, .(to = unlist(strsplit(to,",",T), recursive = F, use.names = F)), by = from]

编辑: 可能更简单的base解决方案会更有效:

library(data.table)
library(magrittr)
data = "1 2,3,4\n2 3,4,5,6"
dt = fread(data, sep = " ", col.names = c("from", "to"))
edges = lapply(strsplit(dt$to, ',', T), as.integer)
cnts = vapply(edges, length, 0L)
res = data.frame(from = rep(dt$from, cnts), 
                 to = unlist(edges, recursive = F, use.names = F))