Menu

Funktionen in R: Definition, Argumente und Rückgabewerte

Wie du in R eine Funktion erstellst - die Syntax function(x) { }, Rückgabewerte, Standard- und benannte Argumente, die ...-Punkte, anonyme Funktionen und wie Scoping funktioniert.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Eine Funktion definieren und aufrufen

Eine Funktion ist in R ein Wert wie eine Zahl oder eine Zeichenkette. Du baust eine mit dem Schlüsselwort function und heftest sie mit <- an einen Namen, genauso wie du alles andere in einer Variablen speichern würdest:

Die Bestandteile: function(x) deklariert einen Parameter namens x, die geschweiften Klammern enthalten den Rumpf, und der Aufruf square(4) führt den Rumpf mit x gleich 4 aus. Bei einem einzeiligen Rumpf sind die geschweiften Klammern optional - square <- function(x) x^2 ist dieselbe Funktion -, aber Klammern lesen sich besser, sobald der Rumpf wächst.

Weil eine Funktion nur ein Wert ist, gilt alles, was du über Variablen weißt: Du kannst sie neu zuweisen, an eine andere Funktion übergeben oder in einer Liste speichern. Diese eine Tatsache trägt die Hälfte des idiomatischen R, einschließlich der ganzen apply-Familie.

Rückgabewerte: Der letzte Ausdruck gewinnt

Eine R-Funktion gibt zurück, was ihr zuletzt ausgewerteter Ausdruck erzeugt. Es gibt keine verpflichtende return-Anweisung:

return() existiert und funktioniert wie erwartet - es beendet die Funktion sofort und gibt sein Argument zurück. Idiomatisches R hebt es sich für frühe Ausstiege auf: das Aussteigen am Anfang, wenn eine Eingabe den Rest der Arbeit sinnlos macht. Kombiniere es mit if-else-Prüfungen:

return(a / b) in die letzte Zeile zu schreiben wäre nicht falsch, nur Rauschen. Reserviere return() für die Ausstiege, die früh passieren, und lass den letzten Ausdruck für den Normalfall sprechen.

Standardwerte und benannte Argumente

Ein Parameter kann einen Standardwert tragen, deklariert mit = in der Parameterliste. Aufrufer, die mit dem Standard zufrieden sind, lassen das Argument einfach weg:

Der dritte Aufruf zeigt die andere Hälfte der Geschichte: benannte Argumente. Schreibst du an der Aufrufstelle name = "Ada", spielt die Position keine Rolle mehr - R gleicht zuerst über Namen ab und füllt die verbleibenden Parameter dann nach Position. Daraus folgen zwei praktische Regeln:

  • Setz erforderliche Parameter nach vorn und solche mit Standardwert dahinter, damit positionsbasierte Aufrufe natürlich bleiben.
  • Benenne an der Aufrufstelle jedes Argument, das sich nicht aus der Position ergibt. greet("Ada", punctuation = "?") ist klarer, als Leser Kommas zählen zu lassen.

Argumente durchreichen mit ...

Der spezielle Parameter ... (gesprochen "dots") bedeutet "beliebig viele zusätzliche Argumente". Eine Funktion, die ... deklariert, kann Argumente annehmen, die sie nie aufgeführt hat, und sie an eine andere Funktion weiterreichen:

shout() weiß und kümmert sich nicht darum, wie viele Wörter du übergibst - es reicht sie alle an paste() weiter. Beachte, dass punctuation nach den Punkten steht: Jeder nach ... deklarierte Parameter lässt sich nur über den Namen setzen, was für Optionen genau richtig ist. Dieses Durchreichmuster steckt überall in Base R - sapply(x, round, digits = 2) funktioniert, weil sapply digits = 2 über sein eigenes ... an round weitergibt.

Der Preis der Punkte ist, dass Tippfehler still durchrutschen: Verschreib dich bei punctuation zu punctation, und es wird einfach von ... verschluckt, statt einen Fehler auszulösen. Halte Funktionen mit Punkten klein.

Anonyme Funktionen

Wird eine Funktion nur einmal gebraucht - typischerweise als Argument einer anderen Funktion -, kannst du den Namen ganz weglassen:

Beide Zeilen tun dasselbe. function(x) x^2 ist die klassische Schreibweise; \(x) x^2 ist die in R 4.1 ergänzte Kurzform, in der \ für das Wort function steht. Sie sind in jeder Hinsicht identisch außer in der Tastenanzahl - die Kurzform ist keine andere Art von Funktion.

Nutze eine anonyme Funktion, wenn die Operation ein Einzeiler an genau einer Aufrufstelle ist. In dem Moment, in dem du dasselbe Lambda an zwei Stellen einfügst oder es über eine Zeile hinauswächst, gib ihm einen Namen - eine benannte Funktion ist testbar und selbstdokumentierend.

Scoping: Was eine Funktion sehen kann

R nutzt lexikalisches Scoping: Wenn eine Funktion eine Variable braucht, die sie unter ihren eigenen Parametern und lokalen Zuweisungen nicht findet, sucht sie in der Umgebung, in der die Funktion definiert wurde - nicht dort, wo sie aufgerufen wurde. In der Praxis heißt das, dass eine Funktion Variablen aus dem umgebenden Skript lesen kann:

Die Kehrseite: Eine Zuweisung innerhalb einer Funktion dringt nie nach außen. rate <- 0.5 in change_inside erzeugt eine frische lokale Variable, die stirbt, wenn die Funktion zurückkehrt; das äußere rate gibt weiterhin 0.1 aus. Das ist ein Feature - Funktionen können deinen Arbeitsbereich nicht versehentlich zertrampeln -, überrascht aber Anfänger, die erwarten, dass die innere Zuweisung bestehen bleibt. Muss eine Funktion ein Ergebnis nach außen geben, gib es zurück und weise es an der Aufrufstelle zu. (Es gibt einen <<--Operator, der nach außen greift; behandle ihn als Code Smell, bis du ihn wirklich brauchst.)

Ein durchgerechnetes Beispiel

Hier ist das lohnende Muster: Du bemerkst, dass du drei Analysezeilen wiederholst, packst sie in eine Funktion und nutzt sie wieder. Nehmen wir an, du fasst ständig Vektoren von Messwerten zusammen:

Alles von dieser Seite steckt darin: ein digits-Parameter mit Standardwert, ein benannter Aufruf, der ihn überschreibt, und ein letzter Ausdruck (round(out, digits)), der die Rückgabe übernimmt. Die Funktion liest sich wie ein Satz, funktioniert auf jedem numerischen Vektor und liegt an einer Stelle, wenn du dich entscheidest, einen Median zu ergänzen.

Was du mitnimmst

  • name <- function(args) { body } erzeugt eine Funktion; der zuletzt ausgewertete Ausdruck ist ihr Rückgabewert.
  • return() ist für frühe Ausstiege, nicht für die normale letzte Zeile.
  • Standardwerte werden mit = in der Parameterliste deklariert; benannte Argumente machen Aufrufstellen reihenfolgeunabhängig und lesbar.
  • ... nimmt beliebige zusätzliche Argumente an und reicht sie weiter - mächtig, aber es verbirgt Tippfehler.
  • function(x) und \(x) sind dasselbe; nutze anonyme Funktionen für einmalige Einzeiler.
  • Funktionen lesen Variablen von dort, wo sie definiert wurden; Zuweisungen in ihnen bleiben drinnen.

Als Nächstes: die apply-Familie - die Funktionen, die deine Funktionen nehmen und über ganze Vektoren und Listen laufen lassen.

Häufig gestellte Fragen

Wie erstellt man eine Funktion in R?

Weise einem Namen ein function-Objekt zu: square <- function(x) { x^2 }. Die Parameter stehen in den runden Klammern, der Rumpf in den geschweiften, und du rufst sie mit square(4) auf. Der zuletzt ausgewertete Ausdruck ist das, was die Funktion zurückgibt.

Braucht man return() in R?

Nein. Eine R-Funktion gibt automatisch den Wert des letzten ausgewerteten Ausdrucks zurück. return() existiert, und idiomatisches R reserviert es für frühe Ausstiege - das Aussteigen am Anfang einer Funktion, wenn eine Eingabe ungültig ist oder ein Sonderfall behandelt wurde.

Was ist eine anonyme Funktion in R?

Eine Funktion, die du ohne Namen definierst, meist direkt an eine andere Funktion übergeben: sapply(x, function(v) v^2). Seit R 4.1 gibt es außerdem die Kurzschreibweise \(v) v^2, die exakt dasselbe mit weniger Tastenanschlägen bedeutet.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S