我有一个表显示事件之间的连接:
library(data.table)
df = data.table(p1 = c("x0", "x0", "x1", "x2", "x3"),
p2 = c("x1", "x2", "x3", "x3", "x4"))
这是一个例子:
仅当所有先前事件均已发生时,下一个事件才可能发生。例如,事件x3可能仅在x1和x2之后发生,而与它们的顺序无关。
如何以data.table方式将df表转换为下一个表(所有事件以某种允许的顺序显示):
df_required = data.table(p = c("x0", "x1", "x2", "x3", "x4",
"x0", "x1", "x2", "x3", "x4"),
sequence = c(1, 2, 3, 4, 5, 1, 3, 2, 4, 5),
group = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2))
必需的表显示了两个可能的连接组:x0-x1-x2-x3-x4和x0-x2-x1-x3-x4。有两种可能的方式,因为两个值可能立即跟随x0:x1或x2。序列也写在插图的圆圈上方。
答案 0 :(得分:2)
我之所以发布它,是因为它提供的输出与罗兰兹的建议相同:
(如果没有意义,我会删除它)
数据:
library(data.table)
df = data.table(p1 = c("x0", "x0", "x1", "x2", "x3"),
p2 = c("x1", "x2", "x3", "x3", "x4"))
代码:
restElements <- setdiff(df$p1, df$p2)
ans <-
t(do.call(
expand.grid, c(restElements, unique(split(df$p2,df$p1)))
))
group = rep(1:ncol(ans), each = nrow(ans))
p = c( ans )
sequence = as.numeric(factor(p))
data.table(p, sequence, group)
结果:
# p sequence group
#1: x0 1 1
#2: x1 2 1
#3: x3 4 1
#4: x4 5 1
#5: x0 1 2
#6: x2 3 2
#7: x3 4 2
#8: x4 5 2
请注意:
确保在设置因子factor(p)
时获得正确的顺序。 (默认情况下,因子级别是仅排序的。适用于此示例,可能不适用于其他示例。)
使用igraph方法可能比我的ans
更为明智。
因此您可以将两者结合在一起
从@Roland借来的
lvls <- levels(factor(c(df$p1, df$p2)))
library(igraph);
tmp <- lapply(all_shortest_paths(graph_from_data_frame(df), lvls[1], lvls[length(lvls)])$res, as.vector)
ans <- sapply(tmp, function(x) { lvls[x] })
您可以使用此ans
。确保以后使用:sequence = as.numeric(factor(p, lvls))
答案 1 :(得分:2)
您可以为每个节点分配一个等级(假设您有a graph for which this makes any sense)...
vdf = data.table(p = sort(unique(unlist(df[, c("p1", "p2")]))))
i = 0L
vdf[, r := 0L]
while (any(vdf[r == i, p] %in% df$p1)){
vdf[r == i, r := r + !df[.(p), on=.(p1), p %in% setdiff(p1, p2)]]
i = i + 1L
}
p r
1: x0 0
2: x1 1
3: x2 1
4: x3 2
5: x4 3
如果有一个独特的第一个事件x0
,那么感谢@Roland,这是一种更简单的方法:
library(igraph)
vdf[, r := as.vector(distances(graph_from_data_frame(df), "x0"))]
然后,对于具有多个节点的每个等级,进行所有排列(此处,从Generating all distinct permutations of a list in R借用)...
wdf = vdf[, do.call(cbind, lapply(split(.I, r), function(x) as.data.table(
gtools::permutations(length(x), length(x), x)
)))]
0.V1 1.V1 1.V2 2.V1 3.V1
1: 1 2 3 4 5
2: 1 3 2 4 5
wdf
中的值是?.I
的行号(请参阅vdf
),所以...
mdf = melt(wdf[, g := .I], id = "g", value.name = "w")[order(g, variable)]
vdf[mdf$w, .(p, g = mdf$g, r)][, seq := rowid(g)][]
p g r seq
1: x0 1 0 1
2: x1 1 1 2
3: x2 1 1 3
4: x3 1 2 4
5: x4 1 3 5
6: x0 2 0 1
7: x2 2 1 2
8: x1 2 1 3
9: x3 2 2 4
10: x4 2 3 5
因此g
是OP中提到的“组”; r
是等级; seq
是组中的序列(很有用,因此表的排序是明确的)。
注释。在将等级/深度属性分配给vdf
中的每个节点后,我将停止。有关可行的事件序列的所有信息都在此处,但是就计算时间和空间而言,对它们进行枚举(如在OP的输出中)可能非常昂贵,因此应尽可能避免。
共享同一等级的事件x
的排列数为factorial(length(x))
,例如,如果x
的长度为10,则返回的矩阵的维度为{{1} } = 3628800 x10。我的计算机在尝试计算时挂起。