2012-07-31 10 views
6

In R für Programmierer Lesen ich diese Funktion sahEine grundlegende R Funktion

oddcount <- function(x) { 
    k <- 0 
    for (n in x) { 
    if (n %% 2 == 1) k <- k+1 
    } 
    return(k) 
} 

ich lieber wäre es in einem einfacheren Stil schreiben (dh in Lisp)

(defn odd-count [xs] 
    (count (filter odd? xs))) 

ich die Funktion Länge sehen ist gleichbedeutend zu zählen und ich kann ungerade schreiben? also gibt es eingebaute karten/filter/remove type funktionen?

Antwort

11

Eine R Weg, dies zu tun wäre, um die for Schleife zu vermeiden, und verwenden Sie Vektorisierung:

oddcount <- function(x) { 
    sum(x %% 2) 
} 

Der Vergleich zwischen x und 2 gibt einen Vektor als x selbst ist ein Vektor. Summe als berechnet die Summe des Vektors, wobei TRUE gleich 1 ist und FALSE gleich Null ist. Auf diese Weise berechnet die Funktion die Anzahl der ungeraden Zahlen im Vektor.

Dies führt bereits zu einer einfacheren Syntax, obwohl die for-Schleife für Nicht-Vektorisierungsorientierte tendenziell einfacher zu lesen ist. Ich bevorzuge die vektorisierte Syntax, da sie viel kürzer ist. Ich würde es vorziehen, einen aussagekräftigeren Namen für x zu verwenden, z.B. number_vector.

+1

In diesem Fall könnte es sogar noch kürzer sein, Sie brauchen nicht unbedingt das '== 1', da' %%' nur 0's und 1's zurückgibt. Verwende 'sum (x %% 2)'. Dies kann auch ein wenig schneller sein, da Sie keine logischen Daten generieren und sie nicht zurück in numerische Werte konvertieren. Einige finden die längere Version besser lesbar (und wenn Sie dies auf die Suche nach Zahlen ausweiten möchten, die ein Vielfaches von 2 sind oder nicht, dann benötigen Sie die längere Version. –

5

Sie sollten einen Blick auf die funprog Bibliothek nehmen, die map umfasst, filter, reduce usw.

+0

Danke, Länge (Filter (odd_p, xs)) scheint die Arbeit zu tun, es scheint, dass ich die falsche Frage auf der Grundlage der letzten Antwort jedoch fragte :) – ChrisR

+0

Es ist nichts falsch mit der Verwendung 'funprog', aber mit Standard R Sie können die gleiche Kürze im Code bekommen. –

+0

Das ist ein guter Punkt, @Paul. Der Versuch, eine Sprache, die ein Paradigma verwendet (vektorisiert), in ein anderes (funktionales) Paradigma zu zwingen, führt oft zu unnötigem Verbose-Code. –

12

In R, wenn Sie mit Vektoren arbeiten, bevorzugen Menschen oft, den gesamten Vektor gleichzeitig zu bearbeiten, anstatt ihn durchzuschleifen (siehe zum Beispiel this Diskussion).

In gewissem Sinne hat R "eingebaute" Filter und Funktionen reduzieren: die Art und Weise, in der Sie Teilmengen eines Vektors auswählen können. Sie sind sehr praktisch in R, und es gibt ein paar Möglichkeiten - Ich werde dir ein Paar zeigen, aber du wirst mehr aufheben, wenn du über R liest und den Code anderer Leute auf einer solchen Seite anschaust. Ich würde auch betrachten ?which und ?'[', die mehr Beispiele als ich hier habe.

Die erste Möglichkeit besteht darin, einfach auszuwählen, welche Elemente Sie möchten.Sie können diese verwenden, wenn Sie die Indizes der Elemente, die Sie wünschen:

x <- letters[1:10] 
> x 
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" 

Wenn wir nur die ersten fünf Buchstaben wollen, können wir schreiben:

x[1:5] 
x[c(1,2,3,4,5)] # a more explicit version of the above 

Sie können auch die Elemente, die Sie auswählen nicht will tun, indem Sie ein Minuszeichen verwenden, zum Beispiel:

x[-(6:10)] 

andere Art und Weise Elemente auszuwählen, ist durch einen booleschen Vektor verwendet:

x <- 1:5 
selection <- c(FALSE, TRUE, FALSE, TRUE, FALSE) 
x[selection] # only the second and fourth elements will remain 

Dies ist wichtig, weil wir einen solchen Vektor, indem man einen Vektor in einer Vergleichsfunktion erstellen:

selection <- (x > 3) 
> selection 
[1] FALSE FALSE FALSE TRUE TRUE 

x[selection] # select all elements of x greater than 3 
x[x > 3]  # a shorthand version of the above 

Wieder einmal können wir das Gegenteil von dem Vergleich wählen wir verwenden (beachten Sie, dass seit es boolean ist, verwenden wir ! und nicht -):

x[!(x > 3)] # select all elements less than or equal to 3 

Wenn Sie Vektor wollen Vergleiche tun, sollten Sie die %in% Funktion prüfen. Zum Beispiel:

x <- letters[1:10] 
> x %in% c("d", "p", "e", "f", "y") 
[1] FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE 

# Select all elements of x that are also "d", "p", "e", "f", or "y" 
x[x %in% c("d", "p", "e", "f", "y")] 
# And to select everything not in that vector: 
x[!(x %in% c("d", "p", "e", "f", "y"))] 

Die oben genannten sind nur ein paar Beispiele; Ich würde die Dokumentation definitiv empfehlen. Ich weiß, dass dies ein langer Post ist, nachdem Sie bereits eine Antwort akzeptiert haben, aber diese Art von Sache ist sehr wichtig und das Verständnis wird Ihnen viel Zeit und Schmerzen in der Zukunft ersparen, wenn Sie neu bei R sind, dachte ich Ich würde ein paar Wege teilen, um es mit dir zu machen.

+0

Danke, das ist definitiv hilfreich. – ChrisR