我有一组“ x 例如, 所以,如果我从一个排序字母表开始, 如何调整行顺序以满足我的约束?另外,我可以确定我的约束是 valid (即,没有一个约束相互矛盾)。library(data.table)
set.seed(0)
ineqs <- unique(data.table(
X = sample(letters, 10, replace = T),
Rel = "<",
Y = sample(letters, 10, replace = T)
))
ineqs
X Rel Y
1: x < b
2: g < f
3: j < e
4: o < r
5: x < j
6: f < u
7: x < m
8: y < s
9: r < z
10: q < j
dt <- data.table(Foo = letters)
Foo
1: a
2: b
3: c
---
24: x
25: y
26: z
答案 0 :(得分:7)
library(igraph)
g = ineqs[, graph_from_edgelist(cbind(X,Y), directed=TRUE)]
o = names(topo_sort(g))
dt[, v := factor(Foo, levels = o, ordered=TRUE)]
dt[order(v)]
Foo v
1: x x
2: g g
3: o o
4: y y
5: q q
6: b b
7: m m
8: f f
9: r r
10: s s
11: j j
12: u u
13: z z
14: e e
15: a <NA>
16: c <NA>
17: d <NA>
18: h <NA>
19: i <NA>
20: k <NA>
21: l <NA>
22: n <NA>
23: p <NA>
24: t <NA>
25: v <NA>
26: w <NA>
Foo v
所有不在ineqs
中的术语都排在最后。
如果您的关系图具有周期,则应该在topo_sort
中得到警告。这说明您在ineqs
中某些术语的任务定义不正确。
答案 1 :(得分:4)
也许我误会了,但这并不是一件小事,不一定有一个唯一的顺序。
让我给你一个例子。考虑条件
X Rel Y
1: x < b
2: g < f
各种订单都是可以想象的
x < g < f < b
g < x < b < f
g < x < f < b
g < f < x < b
x < g < b < f
x < b < g < f
所有这些都满足前两行中列出的条件。
我很想知道穷举和粗略的实现方式,我们会预先计算所有可能的排列,然后消除那些不满足成对条件的排列。
为说明起见,我们将仅使用4个字母和成对条件数据的前两行。
这是我的结果:
首先,我们定义四个字母并使用gtools::permutations
计算所有排列。
char <- c("b", "f", "g", "x")
library(gtools)
perm <- as.data.frame(permutations(length(char), length(char), char))
有24种可能的排列。
我们现在读取成对条件数据
df <- read.table(text =
"X Rel Y
x < b
g < f", header = T)
# Convert factors to character vectors
df[] <- sapply(df, as.character)
我们现在循环抛出排列和成对条件,并标记排列数据中不满足任何成对条件的那些行。
rmv <- c()
for (i in 1:nrow(perm)) {
# Here we loop throw all possible permutations and eliminate those that
# do not fulfil the pairwise conditions
for (j in 1:nrow(df)) {
# Here we loop throw the pairwise conditions
cond <- eval(parse(text = sprintf("`%s`", df[j, "Rel"])))(
which(perm[i, ] == df[j, "X"]),
which(perm[i, ] == df[j, "Y"]))
if (cond == FALSE) {
rmv <- c(rmv, i)
break
}
}
}
然后满足条件的剩余排列就是
perm[-rmv, ]
# V1 V2 V3 V4
#16 g f x b
#17 g x b f
#18 g x f b
#20 x b g f
#23 x g b f
#24 x g f b