我有一些看起来像这样的数据:
+--------+-----------+
| 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中这样做的最佳方法是什么?
答案 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))