R-Funktion zum Erzeugen monotoner (zunehmender oder abnehmender) Permutationen [Duplikat]
Ich versuche, eine effiziente Funktion zu erstellen, um alle monoton ansteigenden Permutationen eines großen Vektors zu erzeugen. Das Reduzieren der Ausgaben von expand.grid
oder gtools::permutations
funktioniert natürlich, aber nur für kleinere Vektoren.
Beispiel:
x = 1:3
Gewünschte Ausgabe:
1, 1, 1
1, 1, 2
1, 1, 3
1, 2, 2
1, 2, 3
1, 3, 3
2, 2, 2
2, 2, 3
2, 3, 3
3, 3, 3
Irgendwelche Vorschläge zur Verwendung von Base R oder vorhandenen Paketen mit dieser Funktion?
BEARBEITEN: Eine ideale Lösung würde vermeiden, den vollständigen Satz von Permutationen für diese Teilmenge zu generieren.
Antworten
Mit data.table
diesem ist ziemlich einfach:
expand.monotonic <- function(x, len=length(x)){
do.call(CJ, lapply(integer(len), function(...) x ))[
eval(parse(text=paste0("V", 2:len, ">=", "V", 1:(len-1), collapse="&") )), ]
}
expand.monotonic(1:3)
V1 V2 V3
1: 1 1 1
2: 1 1 2
3: 1 1 3
4: 1 2 2
5: 1 2 3
6: 1 3 3
7: 2 2 2
8: 2 2 3
9: 2 3 3
10: 3 3 3
Erläuterung:
Erstellen Sie zunächst eine Liste mit den replizierten Vektorzeiten len
. Verwenden Sie data.table::CJ
diese Option, um alle Vektoren zu kreuzen. Und das ist , wo die Magie basiert geschieht auf dem len
einen Ausdruck erstellen im Grunde V2>=V1&V3>=V2
wie V#
ist der Standardname für unbenannte Spalten und Teilmenge von dem Ergebnis der Auswertung des Ausdrucks.
parse(text=paste0("V", 2:len, ">=", "V", 1:(len-1), collapse="&") )
# expression(V2>=V1&V3>=V2)
Hier ist ein Code, der Permutationen mit Wiederholungen erstellt, die wie in Ihrem Beispiel zulässig sind, und erkennt, ob jede Permutation monoton ist
x <- 1:3
# Generate permutations of length x
out <- gtools::permutations(length(x), length(x), v = x, repeats.allowed=TRUE)
# Detect if they're monotonic
mono <- apply(out, 1, function(x) { all(x == cummax(x)) })
output_with_monotonic_label <- cbind(out, mono)
# output_with_monotonic_label
# mono
# [1,] 1 1 1 1
# [2,] 1 1 2 1
# [3,] 1 1 3 1
# [4,] 1 2 1 0
# [5,] 1 2 2 1
# [6,] 1 2 3 1
# [7,] 1 3 1 0
# [8,] 1 3 2 0
# [9,] 1 3 3 1
# [10,] 2 1 1 0
# ....