2013-04-04 6 views
8

Ich bin ziemlich neu in R, aber ich habe viel gesucht und habe keine Antwort auf meine Frage gefunden.Sampling in r ohne aufeinander folgende identische Ziffern

Ich habe einen Vektor mit vielen Wiederholungen von 8 Ziffern:

allNum <- c(rep(1, 70), rep(2, 70), rep(3, 35), rep(4, 35), 
      rep(5, 70), rep(6, 70), rep(7, 35), rep(8, 35)) 

Jetzt möchte ich eine Permutation davon nehmen (vermutlich sample(allNum, 420, replace=FALSE) verwenden), aber ich möchte keine aufeinanderfolgenden identischen Ziffern - zum Beispiel : 1 2 2 8

Gibt es eine einfache Möglichkeit, dies zu tun?

+0

Etwas verwandte: http://stackoverflow.com/questions/14684539/sample-with-a-max/14696912 –

+0

Verwenden 'any (diff (x) == 0) 'um zu überprüfen, ob aufeinanderfolgende identische Ziffern vorhanden sind? Dann weiter Proben nehmen, bis Sie einen finden? – liuminzhao

+0

Was für eine gut reproduzierbare erste Frage! – Gregor

Antwort

0

Entlehnung von a previous answer, eine Methode ist Brute-Force und Probenahme, bis Sie eine Permutation mit den gewünschten Eigenschaften erhalten.

Der folgende Befehl dauert jedoch sehr lange, da identische fortlaufende Ziffern in dem von Ihnen angegebenen Beispiel sehr häufig vorkommen. Dieser Ansatz wäre in Ihrer spezifischen Situation nicht möglich.

3

Sie haben ein Problem, bei dem die Möglichkeit besteht, Elemente willkürlich zu wählen, anstatt auf Ihre Auswahl beschränkt zu sein. Wenn die Anzahl der Elemente, aus denen Sie auswählen müssen, mehr als $ 2n-1 $ beträgt, wobei $ n $ die Häufigkeit ist, mit der das häufigste Element auftritt, können Sie ein zufälliges Element auswählen (konsistent mit den vorherigen Einschränkungen). Wenn diese Zahlen jedoch gleich sind, muss sich der häufigste Wert für den Rest der Sequenz an jeder anderen Position befinden (und die Werte dazwischen können nach dem Zufallsprinzip zugewiesen werden). Das Erkennen dieser Einschränkung ermöglicht einen einzelnen Durchlauf (keine zufälligen Auswahlen mehr, als es Elemente im ursprünglichen Vektor gibt).

permute.nonconsec <- function(allNum) { 
    fully.constrained <- function(x) { 
    2*max(table(x)) - 1 == length(x) 
    } 
    permuted <- numeric(length(allNum)) 
    permuted[1] <- sample(allNum, 1) 
    allNum <- allNum[-min(which(allNum==permuted[1]))] 
    for (i in seq_along(allNum)+1) { 
    if(fully.constrained(allNum)) { 
     # switch to deterministic algorithm 
     # determine which value is the constraining one 
     r <- rle(sort(allNum)) 
     limiter <- r$values[r$lengths==max(r$lengths)] 
     permuted[seq(i, length(permuted), by=2)] <- limiter 
     remaining <- allNum[allNum != limiter] 
     if (length(remaining)>0) { 
     permuted[seq(i+1, length(permuted), by=2)] <- 
      remaining[sample.int(length(remaining))] 
     } 
     break; 
    } 
    available <- allNum[allNum != permuted[i-1]] 
    permuted[i] <- available[sample.int(length(available), 1)] 
    allNum <- allNum[-min(which(allNum==permuted[i]))] 
    } 
    permuted 
} 

Dies wird scheitern, wenn es keine mögliche Anordnung ist: length(x) < 2 * max(table(x)) - 1, aber eine erste Prüfung auf, dass, falls gewünscht hinzugefügt werden könnte.

0

Hier ist ein einfacher Algorithmus für die:

N = 420 
i = as.integer(runif(1, 1, length(allNum))) 
result = allNum[i] 
allNum = allNum[-i] 
while (N != 1) { 
    N = N - 1 

    # pick a random value that's different from last chosen one 
    last = result[length(result)] 
    i = as.integer(runif(1, 1, sum(allNum != last))) 
    result = c(result, allNum[allNum != last][i]) 

    # remove any (doesn't matter which) element of allNum that's 
    # equal to last choice, to sample without replacement 
    last = result[length(result)] 
    allNum = allNum[-which(allNum == last)[1]] 
} 
+0

Das Problem mit diesem Algorithmus ist, dass Sie mit 'allNum' enden können, das den gleichen Wert enthält (zB' allNum = c (2,2) '). In diesem Fall wählt es eine 2 aus, aber dann den nächsten Durchlauf, 'sum (allNum! = last)' ist 0 und es gibt keine verfügbaren/gültigen Werte zum Abtasten. –

+0

Das ist kein Problem. Wenn Sie den Algorithmus mit dieser Eingabe ausführen und 'N = 2' erhalten Sie 'result = c (2, NA)'. So können Sie leicht überprüfen, ob die Stichprobe, die Sie versucht haben, erreichbar war (und Sie erhalten auch den maximal erreichbaren Teil). – eddi

Verwandte Themen