Was bedeutet "S3-Methoden" in R?


124

Da ich ziemlich neu in R bin, weiß ich nicht, was die S3-Methoden und -Objekte sind. Ich habe festgestellt, dass es S3- und S4-Objektsysteme gibt, und einige empfehlen, S3 nach Möglichkeit über S4 zu verwenden (siehe Google R Style Guide unter http://google-styleguide.googlecode.com/svn/trunk/google-r-style). html ) *. Die genaue Definition der S3-Methoden / -Objekte ist mir jedoch nicht bekannt.

Update: Ab 2019 ist der Hyperlink R Style Guide von Google hier .

Antworten:


85

Die meisten relevanten Informationen finden Sie unter ?S3oder ?UseMethod, aber auf den Punkt gebracht:

S3 bezieht sich auf ein Schema des Methodenversands. Wenn Sie R für eine Weile benutzt haben, werden Sie feststellen , dass es print, predictund summaryMethoden für eine Vielzahl von verschiedenen Arten von Objekten.

In S3 funktioniert dies wie folgt:

  • Festlegen der Klasse von Objekten von Interesse (z. B. der Rückgabewert eines Aufrufs der Methode glmhat eine Klasse glm)
  • ein Verfahren , mit dem allgemeinen Namen bereitstellt ( zum Beispiel print), dann ist ein Punkt, und dann die Klassennamen (zB print.glm)
  • Damit printdies funktioniert, müssen einige Vorbereitungen für diesen allgemeinen Namen ( ) getroffen worden sein. Wenn Sie sich jedoch lediglich an vorhandene Methodennamen anpassen möchten, benötigen Sie diese nicht (siehe die Hilfe, auf die ich zuvor verwiesen habe, wenn Sie dies tun) ).

Für den Betrachter und insbesondere für den Benutzer Ihres neu erstellten funky Modell-Anpassungspakets ist es viel bequemer, tippen zu können predict(myfit, type="class")als predict.mykindoffit(myfit, type="class").

Es steckt noch einiges mehr dahinter, aber das sollte Ihnen den Einstieg erleichtern. Diese Art des Versendens von Methoden, die auf einem Attribut (einer Klasse) von Objekten basieren (und C-Puristen liegen wahrscheinlich nachts wach vor Entsetzen), hat einige Nachteile, aber in vielen Situationen funktioniert sie anständig. Mit der aktuellen Version von R wurden neuere Methoden implementiert (S4 und Referenzklassen), aber die meisten Leute verwenden immer noch (nur) S3.


54

Schauen Sie sich den Code für die medianFunktion an , um mit S3 zu beginnen . Wenn Sie medianan der Eingabeaufforderung tippen, wird angezeigt, dass der Text eine Zeile enthält

UseMethod("median")

Das heißt, es ist eine S3-Methode. Mit anderen Worten, Sie können medianfür verschiedene S3-Klassen eine andere Funktion haben . Geben Sie Folgendes ein, um alle möglichen Medianmethoden aufzulisten

methods(median) #actually not that interesting.  

In diesem Fall gibt es nur eine Methode, die Standardmethode, die für alles aufgerufen wird. Sie können den Code dafür sehen, indem Sie eingeben

median.default

Ein viel interessanteres Beispiel ist die printFunktion, die viele verschiedene Methoden hat.

methods(print)  #very exciting

Beachten Sie, dass einige der Methoden *s neben ihrem Namen haben. Das bedeutet, dass sie im Namespace eines Pakets versteckt sind. Verwenden findSie diese Option , um herauszufinden, in welchem ​​Paket sie sich befinden. Zum Beispiel

find("acf")  #it's in the stats package
stats:::print.acf

39

Von http://adv-r.had.co.nz/OO-essentials.html :

Die drei OO-Systeme von R unterscheiden sich in der Definition von Klassen und Methoden:

  • S3 implementiert einen OO-Programmierstil namens OO mit generischer Funktion. Dies unterscheidet sich von den meisten Programmiersprachen wie Java, C ++ und C #, die OO für die Nachrichtenübermittlung implementieren. Bei der Nachrichtenübermittlung werden Nachrichten (Methoden) an Objekte gesendet, und das Objekt bestimmt, welche Funktion aufgerufen werden soll. In der Regel hat dieses Objekt im Methodenaufruf ein besonderes Erscheinungsbild, das normalerweise vor dem Namen der Methode / Nachricht angezeigt wird: z. B. canvas.drawRect ("blau"). S3 ist anders. Während Berechnungen noch über Methoden ausgeführt werden, entscheidet ein spezieller Funktionstyp, der als generische Funktion bezeichnet wird, welche Methode aufgerufen werden soll, z. B. drawRect (Zeichenfläche, "blau"). S3 ist ein sehr lässiges System. Es gibt keine formale Definition von Klassen.

  • S4 funktioniert ähnlich wie S3, ist jedoch formeller. Es gibt zwei Hauptunterschiede zu S3. S4 verfügt über formale Klassendefinitionen, die die Darstellung und Vererbung für jede Klasse beschreiben, und über spezielle Hilfsfunktionen zum Definieren von Generika und Methoden. S4 hat auch mehrere Versendungen, was bedeutet, dass generische Funktionen Methoden basierend auf der Klasse einer beliebigen Anzahl von Argumenten auswählen können, nicht nur einer.

  • Referenzklassen, kurz RC genannt, unterscheiden sich stark von S3 und S4. RC implementiert OO für die Nachrichtenübermittlung, sodass Methoden zu Klassen und nicht zu Funktionen gehören. $ wird zum Trennen von Objekten und Methoden verwendet, sodass Methodenaufrufe wie Canvas $ drawRect ("blau") aussehen. RC-Objekte sind auch veränderlich: Sie verwenden nicht die übliche Semantik zum Kopieren und Ändern von R, sondern werden an Ort und Stelle geändert. Dies macht es schwieriger, über sie nachzudenken, ermöglicht es ihnen jedoch, Probleme zu lösen, die mit S3 oder S4 schwer zu lösen sind.

Es gibt auch ein anderes System, das nicht ganz OO ist, aber es ist wichtig, hier zu erwähnen:

  • Basistypen, die internen C-Level-Typen, die den anderen OO-Systemen zugrunde liegen. Basistypen werden meistens mit C-Code manipuliert, aber es ist wichtig, sie zu kennen, da sie die Bausteine ​​für die anderen OO-Systeme darstellen.

11

Ich kam zu dieser Frage und fragte mich hauptsächlich, woher die Namen kamen. Aus diesem Wikipedia-Artikel geht hervor, dass sich der Name auf die Version der S-Programmiersprache bezieht, auf der R basiert. Die in den anderen Antworten beschriebenen Methodenverteilungsschemata stammen von S und sind je nach Version entsprechend gekennzeichnet.


10

Versuchen

methods(residuals)

die unter anderem "Residuen.lm" und "Residuen.glm" auflistet. Dies bedeutet, wenn Sie ein lineares Modell, m und Typ angepasst habenresiduals(m), Residuen.lm wird aufgerufen. Wenn Sie ein verallgemeinertes lineares Modell angepasst haben, wird resids.glm aufgerufen. Es ist eine Art C ++ - Objektmodell, das auf den Kopf gestellt wurde. In C ++ definieren Sie eine Basisklasse mit virtuellen Funktionen, die von abgeleiteten Klassen überschrieben werden. In R definieren Sie eine virtuelle (auch als generische) Funktion und entscheiden dann, welche Klassen diese Funktion überschreiben (auch als Methode definieren). Beachten Sie, dass die Klassen, die dies tun, nicht von einer gemeinsamen Superklasse abgeleitet werden müssen. Ich würde nicht zustimmen, S3 generell S4 vorzuziehen. S4 hat mehr Formalismus (= mehr Typisierung) und dies kann für einige Anwendungen zu viel sein. S4-Klassen können jedoch wie eine Klasse oder Struktur in C ++ definiert werden. Sie können angeben, dass ein Objekt einer bestimmten Klasse aus einer Zeichenfolge und zwei Zahlen besteht, zum Beispiel:

setClass("myClass", representation(label = "character", x = "numeric", y = "numeric"))

Methoden, die mit einem Objekt dieser Klasse aufgerufen werden, können sich darauf verlassen, dass das Objekt diese Mitglieder hat. Das unterscheidet sich sehr von S3-Klassen, die nur eine Liste einer Reihe von Elementen sind.

Mit S3 und S4 rufen Sie eine Mitgliedsfunktion nach fun(object, args)und nicht nach auf object$fun(args). Wenn Sie nach etwas Ähnlichem suchen, schauen Sie sich das Protopaket an.


Ich bin mir ziemlich sicher, dass die Idee von Elementfunktionen und Methoden, die zu Objekten gehören, in R nicht so viel Sinn macht. Methoden gehören nicht zu Objekten (auch Funktionen sind auch Objekte), sondern zur Funktion.
Petermeissner

3

Hier wird aktualisiert , um eine schnelle Überblick über die zahlreichen R Objektsysteme nach „Advanced R, 2. Auflage“ (CRC Press, 2019) von Hadley Wickham (Chief Scientist bei RStudio), die eine Web - Darstellung hat hier , bezogen auf das Kapitel über Object -Orientierte Programmierung .

Advanced R Buchcover

Die erste Ausgabe von 2015 hat eine Web - Darstellung hier , mit dem entsprechenden Kapitel über OO hier .

Ansätze für OO-Systeme

Hadley definiert Folgendes, um zwei unterschiedliche Ansätze für die OO-Programmierung zu unterscheiden:

Funktionale OOP : Methoden (aufrufbare Codeteile) gehören zu generischen Funktionen (nicht zu verwechseln mit generischen Java / C # -Methoden ). Stellen Sie sich die Methoden in einer globalen Nachschlagetabelle vor. Die auszuführende Methode wird vom Laufzeitsystem basierend auf dem Namen der Funktion und dem Typ (oder der Objektklasse) eines oder mehrerer an diese Funktion übergebener Argumente gefunden (dies wird als "Methodenversand" bezeichnet). In Bezug auf die Syntax können Methodenaufrufe wie normale Funktionsaufrufe aussehen : myfunc(object, arg1, arg2). Dieser Aufruf würde dazu führen , die Laufzeit für das Verfahren zu dem Paar zugeordnet suchen ( "myfunc", typeof (Objekt)) oder möglicherweise ( "myfunc", typeof (Objekt), typeof (arg1), typeof (arg2))wenn die Sprache das unterstützt. In R S3 gibt der vollständige Name der generischen Funktion das Paar (Funktionsname, Klasse) an . Beispiel: mean.Dateist die Methode zur Berechnung des Mittelwerts von Datumsangaben. Versuchen Sie methods("mean"), die generischen Methoden mit dem Funktionsnamen aufzulisten mean. Der funktionale OOP-Ansatz findet sich beispielsweise im OO-Pionier Smalltalk , im Common Lisp Object System und in Julia . Hadley merkt an, dass "Julias Implementierung im Vergleich zu R voll entwickelt und äußerst performant ist."

Eingekapseltes OOP : Methoden gehören zu Objekten oder Klassen, und Methodenaufrufe sehen normalerweise so aus object.method(arg1, arg2). Dies wird als gekapselt bezeichnet, da das Objekt sowohl Daten (Felder) als auch Verhalten (Methoden) kapselt . Stellen Sie sich die Methode in einer Nachschlagetabelle vor, die an das Objekt oder die Klassenbeschreibung des Objekts angehängt ist. Die Laufzeit sucht die Methode basierend auf dem Methodennamen und möglicherweise dem Typ eines oder mehrerer Argumente. Dies ist der Ansatz, der in "populären" OO-Sprachen wie C ++, Java, C # zu finden ist.

In beiden Fällen kann die Laufzeit, wenn die Vererbung unterstützt wird (wahrscheinlich auch), die Klassenhierarchie nach oben durchlaufen, bis eine Übereinstimmung mit dem Aufrufsuchschlüssel gefunden wurde.

So finden Sie heraus, zu welchem ​​System ein R-Objekt gehört

library(sloop) # formerly, "pryr"
otype(mtcars)
#> [1] "S3"

Die R-Objektsysteme

S3

  • Funktionaler OOP-Ansatz.
  • Wichtigstes System nach Hadley.
  • Am einfachsten, am häufigsten. Erstes OO-System von R.
  • Kommt mit Basis R, die in der gesamten Basis R verwendet wird.
  • Verlässt sich eher auf Konventionen als auf erzwungene Garantien.
  • Siehe Chambers, John M und Trevor J Hastie. 1992. Statistische Modelle in S. Wadsworth & Brooks / Cole Fortgeschrittene Bücher & Software.
  • Details in "Advanced R, 2. Auflage" hier .

S4

  • Funktionaler OOP-Ansatz.
  • Drittwichtigstes System nach Hadley.
  • Umschreiben von S3, daher ähnlich wie S3, jedoch formeller und strenger: Es zwingt Sie, sorgfältig über das Programmdesign nachzudenken. Geeignet für den Bau großer Systeme (z. B. das Bioconductor- Projekt).
  • Implementiert im Basispaket "Methoden".
  • Siehe: Chambers, John M. 1998. "Programmieren mit Daten: Ein Leitfaden für die S-Sprache." Springer.
  • Details in "Advanced R, 2. Auflage" hier .

RC aka "Referenzklassen"

  • Eingekapselter OOP-Ansatz.
  • Kommt mit Basis R.
  • Basierend auf S4.
  • RC-Objekte sind spezielle S4-Objekte, die auch "veränderlich" sind. Das heißt, anstatt die übliche Semantik zum Kopieren und Ändern von R zu verwenden, können sie direkt geändert werden. Beachten Sie, dass der veränderbare Status schwer zu begründen ist und hässliche Fehler verursacht, in bestimmten Anwendungen jedoch zu effizienterem Code führen kann.

R6

  • Eingekapselter OOP-Ansatz.
  • Zweitwichtigstes System nach Hadley.
  • Kann im R6- Paket gefunden werden (installieren mit library(R6))
  • Ähnlich wie RC, aber leichter und viel schneller: Es hängt nicht von S4 oder dem Methodenpaket ab . Errichtet auf R-Umgebungen. Hat auch:
    • öffentliche und private Methoden
    • aktive Bindungen (Felder, die beim Zugriff tatsächlich eine Methode aufrufen)
    • Klassenvererbung, die paketübergreifend funktioniert
    • beide Klassenmethoden (Code, der zu der Klasse gehört , und eine Instanz über zugreifen kann self, private, super) und Elementfunktionen (Funktionen Felder zugeordnet, die jedoch nicht die Methoden, nur Funktionen)
  • Bietet eine standardisierte Möglichkeit, sich der Semantik "Copy-on-Modify" von R zu entziehen
  • Siehe die Paketseite: "R6: Eingekapselte objektorientierte Programmierung für R" .
  • Details in "Advanced R, 2. Auflage" hier .

Andere

Es gibt andere, wie R.oo (ähnlich wie RC), Proto (prototypbasiert, denken Sie an JavaScript) und Mutatr . "Advanced R" sagt jedoch:

Abgesehen von R6, das weit verbreitet ist, sind diese Systeme in erster Linie von theoretischem Interesse. Sie haben ihre Stärken, aber nur wenige R-Benutzer kennen und verstehen sie, sodass es für andere schwierig ist, Ihren Code zu lesen und dazu beizutragen.

Lesen Sie auch das Kapitel über Kompromisse in "Advanced R, 2nd Edition" .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.