2013-01-07 4 views
7

Ich möchte eine Funktion ausführen, die zwei Vektoren betrachtet und je nach Vorzeichen der Werte in den beiden Vektoren unterschiedliche Werte zurückgibt. Ich habe eine Funktion geschrieben, die zwei Werte vergleichen kann, aber dann möchte ich das auf zwei Vektoren ausführen. Also habe ich sapply benutzt, aber ich bekomme andere Ergebnisse als erwartet.sapply mit benutzerdefinierter Funktion (Reihe von if-Anweisungen)

bear.correction<- function(x,y){ 
           if(x > 0 && y < 0){ 
            return(90) 
           }else if(x < 0 && y < 0){ 
            return(180) 
           }else if(x < 0 && y > 0){ 
            return(270) 
           }else return(0) 
           } 

Das folgende gibt das erwartete (und gewünschtes) Ergebnis:

bear.correction(1,-1) 
    bear.correction(1,1) 
    bear.correction(-1,1) 
    bear.correction(-1,-1) 

Ergebnis: 90, 0, 270, 180

aber wenn ich versuche, die gleichen Vergleiche zu tun, sondern mit ich Vektoren mit sapply bekommen ein anderes Ergebnis:

x <- c(1,1,-1,-1) 
    y <- c(-1,1,1,-1) 
    sapply(x,bear.correction,y) 

Ergebnis: 90, 90, 180, 180.

Ich kann nicht sehen, was falsch ist, also bitte helfen!

+0

Es tut mir leid @agstudy, ich dachte, es war möglich, mehrere Antworten zu akzeptieren, aber anscheinend nicht. Ich denke, Stephan Kolossas Antwort war die beste, obwohl die anderen alle auch funktionieren, daher meine positiven Kommentare. –

+1

kein Problem. Ich hoffe, das hilft. – agstudy

Antwort

11

Sie mapply() statt sapply() verwendet werden soll:

mapply(bear.correction,x,y) 

Warum? Ihre sapply() gilt bear.correction() jeden Eintrag von x ... aber ihm den gesamteny Vektor als zweites Argument in jedem Fall und so bear.correction() sieht nur auf dem ersten Eintrag in y in allen vier Fällen zu geben. Um mehrere Einträge in mehreren Vektoren (oder anderen Datenstrukturen) "zu durchlaufen", verwenden Sie mapply().

+0

Danke Stephan. Gute Antwort und klare Erklärung. Ich war nicht bewusst von Mapply() –

5

Sie sollten stattdessen sapply von verwenden mapply

mapply(bear.correction,x,y) 

[1] 90 0 270 180 
+1

Danke, schnell und prägnant. Stephen gab auch eine schöne Erklärung. –

+2

Für zukünftige Referenz auf * apply Funktionen überprüfen Sie diese [Frage] (http://stackoverflow.com/questions/3505701/r-grouping-functions-sapply-vs-lapply-vs-apply-vs-tapply-vs-by-by- vs-aggrega) –

+0

Danke. Das ist eine wirklich hilfreiche Ressource. Ich werde das Lesezeichen setzen. –

4

legte eine browser() in Ihrer Funktion wie folgt aus:

bear.correction<- function(x,y){ 

    browser() 
    if(x > 0 && y < 0){ 
    return(90) 
    }else if(x < 0 && y < 0){ 
    return(180) 
    }else if(x < 0 && y > 0){ 
    return(270) 
    }else return(0) 
} 

Sie werden sehen, was genau geben als parametrs:

Browse[1]> x 
[1] 1 
Browse[1]> y 
[1] -1 1 1 -1 

So wie andere hier gesagt, Sie brauchen mapply verwenden skalare Werte zu geben, , nicht atomarer Vektor.

aber ich denke, hier plyr mit wirklich einfacher (schön Ausgabeformat)

library(plyr) 
dat <- data.frame(x=x,y=y) 
ddply(dat,.(x,y),function(r) bear.correction(r$x,r$y)) 
    x y V1 
1 -1 -1 180 
2 -1 1 270 
3 1 -1 90 
4 1 1 0 
+0

Danke, es ist nützlich, den Debugging-Rat zu haben. Die Pylr-Alternative ist auch nett. Ich habe Pylr nicht viel benutzt, aber es ist ein gutes Paket. –

3

Wenn Sie apply verwenden Sie haben ein bisschen Ihre Funktion ändern:

bear.correction<- function(xy){ 
           if(xy[1] > 0 && xy[2] < 0){ 
            return(90) 
           }else if(xy[1] < 0 && xy[2] < 0){ 
            return(180) 
           }else if(xy[1] < 0 && xy[2] > 0){ 
            return(270) 
           }else return(0) 
           } 

Die Funktion jetzt Nimmt einen Vektor von 2 Werten xy und verwendet das erste wie Ihr altes x und das zweite wie Ihr altes y

x <- c(1,1,-1,-1) 
y <- c(-1,1,1,-1) 

xyx<-cbind(x,y) 


apply(xyx,1, bear.correction) 
+0

Danke. Dies ist auch eine nette Lösung. –