2016-11-15 3 views
0

Sagen, ich habe zwei VektorenKombinationen von Kombinationen in R

upVariables<-c("up1", "up2", "up3", "up4", "up5") 
downVariables<-c("down1", "down2", "down3", "down4", "down5") 

Jeder von ihnen wird eine Nummer in einer anderen Vektoren suchen verwendet werden. Ich suche nach allen möglichen Mengen von zwei Verhältnissen (alle möglichen Mengen von vier Variablen, zwei von jedem Vektor), wobei der Zähler immer aus upVariables ist, der Demominator immer aus downVariables und die letzte Menge nicht die gleiche Variable verwendet zweimal.

Ich habe so weit wie

upCombos<-combn(upVariables,2) 
downCombos<-combn(downVariables,2) 
combos<-arrange(expand.grid(upCombos=upCombos[,1],downCombos=downCombos[,1]),upCombos) 

bekam ich nur hier die erste mögliche Kombination verwendet wird, zu veranschaulichen, aber ich würde wollen alle möglichen Kombinationen iterieren. Das gibt mir:

> combos 
    upCombos downCombos 
1  up1  down1 
2  up1  down2 
3  up2  down1 
4  up2  down2 

Was möchte ich von diesem obwohl produzieren zwei Sätze, so etwas wie:

> combos[1] 
    upCombos downCombos 
1  up1  down1 
2  up2  down2 

und

> combos[2] 
    upCombos downCombos 
1  up1  down2 
2  up2  down1 

so dass in jedem Fall, die jeweils Der Wert von upCombos wird nur einmal verwendet und jeder Wert von downCombos wird nur einmal verwendet. Ist das sinnvoll? Irgendwelche Ideen wie man das macht?

Idealerweise würde ich dann gerne in der Lage sein, Sätze von 3 aus den Originalvektoren anstatt 2er-Sätze zu verallgemeinern, aber ich werde glücklich sein, Sätze von 2 Arbeiten für jetzt zu bekommen.

** Edit Also Jota hat eine Lösung zur Verfügung gestellt, die die Anordnungen innerhalb einer Gruppe von 4 Variablen (2 von upVariables, 2 von downVariables) zur Verfügung stellt. Ich sehe immer noch nicht, wie ich über alle möglichen Mengen von 4 Variablen iteriere. Das Nächste, was ich habe, ist, Jotas Vorschlag in zwei for-Schleifen zu setzen (sehe den noch-nicht-R-Programmierer). Dies liefert viel weniger Kombinationen, als es sein sollte.

n<-2 
offset<-n-1 
for (i in 1:(length(upVariable)-offset)){ 
    for (j in 1:(length(downVariables)-offset)){ 
    combos <- expand.grid(upVariables[i:(i+offset)], downVariables[j:(j+offset)]) 
    combos <- combos[with(combos, order(Var1)), ] # use dplyr::arrange if you prefer 
    mat <- matrix(1:n^2, byrow = TRUE, nrow = n) 
    for(j in 2:nrow(mat)) mat[j, ] <- mat[j, c(j:ncol(mat), 1:(j - 1))] 
     pairs<-(split(combos[c(mat), ], rep(1:n, each = n))) 
    collapsed<-sapply(lapply(pairs, apply, 1, paste, collapse = '_'), paste, collapse = '-') 
     ratioGroups<-c(ratioGroups,collapsed) 
    } 
} 

Dies gibt nur 16 Variablensätze zurück (jeweils mit 2 Kombinationen, also insgesamt 32). Mit 5 Variablen in jedem Satz gibt es jedoch viel mehr Möglichkeiten.

Antwort

0

Also ich denke, ich es geknackt haben . Ich habe ein paar Antworten auf andere Fragen geplündert. Es gibt eine Funktion here namens expand.grid.unique, die Duplikate entfernt, wenn Sie den gleichen Vektor zweimal in expand.grid setzen. Und es gibt eine here, genannt expand.grid.df, die ich nicht einmal vorgeben werde zu verstehen, welche expand.grid expandiert, um auf Datenrahmen zu arbeiten.Sie tun jedoch gemeinsam, was ich möchte.

upVariables<-c("up1", "up2", "up3", "up4", "up5") 
downVariables<-c("down1", "down2", "down3", "down4", "down5") 
ratioGroups<-data.frame(matrix(ncol=2, nrow=0)) 
colnames(ratioGroups)<-c("mix1","mix2") 

ups<-expand.grid.unique(upVariables,upVariables) 
downs<-expand.grid.unique(downVariables,downVariables) 
comboList<-expand.grid.df(ups,downs) 
comboList <- data.frame(lapply(comboList, as.character), stringsAsFactors=FALSE) 
colnames(comboList)<-c("u1","u2","d1","d2") 

Es gibt eine Reihe von faffing über dort in alles wieder in Strings konvertiert werden, weil alles Faktoren aus irgendeinem Grund umgewandelt wird.

Wenn ich Jota Antwort in eine Funktion setzen:

getGroups<-function(line){ 
    n<-2 #the number ratios being used. 
    combos <- expand.grid(as.character(line[1:2]), as.character(line[3:4])) 
    combos <- combos[with(combos, order(Var1)), ] # use dplyr::arrange if you prefer 
    mat <- matrix(1:n^2, byrow = TRUE, nrow = n) 
    for(j in 2:nrow(mat)) mat[j, ] <- mat[j, c(j:ncol(mat), 1:(j - 1))] 
    pairs<-(split(combos[c(mat), ], rep(1:n, each = n))) 
    collapsed<-sapply(lapply(pairs, apply, 1, paste, collapse = '_'), paste, collapse = '-') 
} 

kann ich dann verwenden

ratiosGroups<-as.vector(apply(comboList,1,getGroups)) 

eine Liste aller möglichen Kombinationen zurückzukehren. Ich schätze, das ist immer noch nicht der beste Weg, mein größeres Ziel zu erreichen, aber es wird dahin.

0

könnten Sie expand.grid verwenden Kombinationen zu erstellen und vorzubereiten Subsets mit regulären Ausdrücken

upVariables<-c("up1", "up2", "up3", "up4", "up5") 
downVariables<-c("down1", "down2", "down3", "down4", "down5") 

DF = expand.grid(upVariables,downVariables) 

DF$suffix1 = as.numeric(unlist(regmatches(DF$Var1,gregexpr("[0-9]+",DF$Var1)))) 

DF$suffix2 = as.numeric(unlist(regmatches(DF$Var2,gregexpr("[0-9]+",DF$Var2)))) 

head(DF) 
# Var1 Var2 suffix1 suffix2 
#1 up1 down1  1  1 
#2 up2 down1  2  1 
#3 up3 down1  3  1 
#4 up4 down1  4  1 
#5 up5 down1  5  1 
#6 up1 down2  1  2 



DF_Comb1 = DF[DF$suffix1==DF$suffix2,] 
DF_Comb2 = DF[DF$suffix1!=DF$suffix2,] 

DF_Comb1 
# Var1 Var2 suffix1 suffix2 
# 1 up1 down1  1  1 
# 7 up2 down2  2  2 
# 13 up3 down3  3  3 
# 19 up4 down4  4  4 
# 25 up5 down5  5  5 


head(DF_Comb2) 
    # Var1 Var2 suffix1 suffix2 
# 2 up2 down1  2  1 
# 3 up3 down1  3  1 
# 4 up4 down1  4  1 
# 5 up5 down1  5  1 
# 6 up1 down2  1  2 
# 8 up3 down2  3  2 
0

Hier ist, was ich mit den Kommentaren in Reaktion kam und die editierte Frage.

# create combos and order them according to the first variable 
combos <- expand.grid(upVariables[1:2], downVariables[1:2]) 
combos <- combos[with(combos, order(Var1)), ] # use dplyr::arrange if you prefer 
# if names are important, set them: 
# names(combos) <- c("upCombos", "downCombos") 

# create a matrix to use to sort combos 
mat <- matrix(1:2^2, byrow = TRUE, nrow = 2) 
# take some code from Carl Witthoft to shift the above matrix 
# from: http://stackoverflow.com/a/24144632/640595 
for(j in 2:nrow(mat)) mat[j, ] <- mat[j, c(j:ncol(mat), 1:(j - 1))] 

# use the matrix to sort combos, and then conduct the splitting 
initialResult <- split(combos[c(mat), ], rep(1:2, each = 2)) 
$`1` 
    Var1 Var2 
1 up1 down1 
4 up2 down2 

$`2` 
    Var1 Var2 
3 up1 down2 
2 up2 down1 

Um den Rest der Kombinationen zu erzeugen, können wir durch laufen und die oben Variablen und unten Variablen ersetzen:

# use regular expressions with the stringi package to produce the rest of the combinations. 
library(stringi) 
# convert from factor to character for easier manipulation 
initialResult <- lapply(initialResult, sapply, as.character) 

# iterate through the columns of upCombos 
intermediateResult <- lapply(seq_len(dim(upCombos)[2]), 
    function(ii) { 
     jj <- stri_replace_all_fixed(unlist(initialResult), 
      pattern = c("up1", "up2"), 
      replacement = c(upCombos[, ii])) 
     relist(jj, initialResult)}) 

# iterate through columns of downCombos 
finalResult <- lapply(seq_len(dim(downCombos)[2]), 
    function(ii) { 
     jj <- stri_replace_all_fixed(unlist(intermediateResult), 
      pattern = c("down1", "down2"), 
      replacement = c(downCombos[, ii]), vectorize_all = FALSE) 
     relist(jj, intermediateResult)}) 
+0

Also das funktioniert, um alle Kombinationen für eine bestimmte Menge von Variablen zu erhalten. Wie ändere ich das so, dass es über alle möglichen Kombinationen von up1: up5 und down2: down5 iteriert? Mein erster Gedanke war, dass in diesem Fall zwei for-Schleifen, dh für (i in 1: (Länge (upVariables) -offset)) usw. Dies scheint a) nicht sehr R wie - ich bin sicher, es gibt einen besseren Weg, dies zu tun und b) es scheint nicht annähernd so viele Kombinationen hervorzubringen, wie ich dachte. – Ben

+0

Ich bezog mich auf das Bit an der Spitze meiner Frage, wo ich erwähnte, dass ich zwei Sätze von Variablen hatte, upVariables und downVariables, und dass ich alle möglichen Kombinationen von 4 Variablen (2 von jedem) bekommen wollte. Ich benutzte den ersten Satz von vier, um zu zeigen, was ich mit jedem einzelnen Set machen wollte. Deine Antwort funktioniert hervorragend, um die Variablen mit jedem Satz von 4 zu arrangieren. Ich dachte, ich wäre in der Lage, sie zu erweitern, um über alle möglichen Mengen zu iterieren, aber es scheint nicht möglich zu sein. Ich werde zurückgehen und sehen, ob ich die Frage besser formulieren kann. – Ben

+0

Ich ... kann etwas haben. Wird eine Antwort posten. – Ben