Que signifie «méthodes S3» dans R?

125

Comme je suis assez nouveau dans R, je ne sais pas ce que sont les méthodes et les objets S3. J'ai trouvé qu'il existe des systèmes d'objets S3 et S4, et certains recommandent d'utiliser S3 sur S4 si possible (voir le guide de style R de Google à http://google-styleguide.googlecode.com/svn/trunk/google-r-style. html ) *. Cependant, je ne connais pas la définition exacte des méthodes / objets S3.

Mise à jour: à partir de 2019, le lien hypertexte du guide de style R de Google est maintenant disponible .

jiggysoo
la source

Réponses:

85

La plupart des informations pertinentes peuvent être trouvées en regardant ?S3ou ?UseMethod, mais en un mot:

S3 fait référence à un schéma de distribution de méthode. Si vous avez utilisé R pendant un certain temps, vous remarquerez qu'il ya print, predictet des summaryméthodes pour beaucoup de différents types d'objets.

Dans S3, cela fonctionne par:

  • définition de la classe des objets d'intérêt (ex: la valeur de retour d'un appel à une méthode glma une classe glm)
  • la fourniture d' un procédé avec le nom général (par exemple print), puis un point, puis le nom de classe (par exemple print.glm)
  • une certaine préparation doit avoir été faite à ce nom général ( print) pour que cela fonctionne, mais si vous cherchez simplement à vous conformer aux noms de méthodes existants, vous n'en avez pas besoin (voir l'aide à laquelle j'ai fait référence plus tôt si vous le faites ).

Pour l'œil du spectateur, et en particulier, l'utilisateur de votre nouveau package de montage de modèle funky, il est beaucoup plus pratique de pouvoir taper predict(myfit, type="class")que predict.mykindoffit(myfit, type="class").

Il y a un peu plus, mais cela devrait vous aider à démarrer. Il y a pas mal d'inconvénients à cette façon de distribuer des méthodes basées sur un attribut (classe) d'objets (et les puristes C restent probablement éveillés la nuit avec horreur), mais pour beaucoup de situations, cela fonctionne décemment. Avec la version actuelle de R, de nouvelles méthodes ont été implémentées (S4 et classes de référence), mais la plupart des gens utilisent encore (uniquement) S3.

Nick Sabbe
la source
55

Pour vous familiariser avec S3, regardez le code de la medianfonction. Taper medianà l'invite de commande révèle qu'il a une ligne dans son corps, à savoir

UseMethod("median")

Cela signifie qu'il s'agit d'une méthode S3. En d'autres termes, vous pouvez avoir une medianfonction différente pour différentes classes S3. Pour lister toutes les méthodes médianes possibles, tapez

methods(median) #actually not that interesting.  

Dans ce cas, il n'y a qu'une seule méthode, la méthode par défaut, qui est appelée pour n'importe quoi. Vous pouvez voir le code pour cela en tapant

median.default

Un exemple beaucoup plus intéressant est la printfonction, qui a de nombreuses méthodes différentes.

methods(print)  #very exciting

Notez que certaines méthodes ont des *s à côté de leur nom. Cela signifie qu'ils sont cachés dans l'espace de noms de certains packages. Permet findde savoir dans quel package ils se trouvent. Par exemple

find("acf")  #it's in the stats package
stats:::print.acf
Coton Richie
la source
39

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

Les trois systèmes OO de R diffèrent dans la façon dont les classes et les méthodes sont définies:

  • S3 implémente un style de programmation OO appelé OO à fonction générique. Ceci est différent de la plupart des langages de programmation, comme Java, C ++ et C #, qui implémentent OO de transmission de messages. Avec la transmission de messages, les messages (méthodes) sont envoyés aux objets et l'objet détermine la fonction à appeler. Typiquement, cet objet a une apparence spéciale dans l'appel de méthode, apparaissant généralement avant le nom de la méthode / du message: par exemple canvas.drawRect ("blue"). S3 est différent. Alors que les calculs sont toujours effectués via des méthodes, un type spécial de fonction appelé fonction générique décide de la méthode à appeler, par exemple, drawRect (canvas, "blue"). S3 est un système très informel. Il n'a pas de définition formelle des classes.

  • S4 fonctionne de manière similaire à S3, mais est plus formel. Il existe deux différences majeures avec S3. S4 a des définitions de classe formelles, qui décrivent la représentation et l'héritage de chaque classe, et a des fonctions d'assistance spéciales pour définir les génériques et les méthodes. S4 a également une répartition multiple, ce qui signifie que les fonctions génériques peuvent choisir des méthodes basées sur la classe de n'importe quel nombre d'arguments, pas seulement un.

  • Les classes de référence, appelées RC en abrégé, sont assez différentes de S3 et S4. RC implémente l'OO de transmission de messages, les méthodes appartiennent donc à des classes et non à des fonctions. $ est utilisé pour séparer les objets et les méthodes, donc les appels de méthode ressemblent à canvas $ drawRect ("blue"). Les objets RC sont également modifiables: ils n'utilisent pas la sémantique habituelle de copie sur modification de R, mais sont modifiés sur place. Cela les rend plus difficiles à raisonner, mais leur permet de résoudre des problèmes difficiles à résoudre avec S3 ou S4.

Il y a aussi un autre système qui n'est pas tout à fait OO, mais il est important de le mentionner ici:

  • types de base, les types internes de niveau C qui sous-tendent les autres systèmes OO. Les types de base sont principalement manipulés à l'aide de code C, mais ils sont importants à connaître car ils fournissent les éléments constitutifs des autres systèmes OO.
Amit K Thakur
la source
12

Je suis venu à cette question en me demandant surtout d'où venaient les noms. Il ressort de cet article de wikipedia que le nom fait référence à la version du langage de programmation S sur laquelle R est basé. Les schémas de répartition de méthode décrits dans les autres réponses proviennent de S et sont étiquetés de manière appropriée selon la version.

Jonathan Adelson
la source
10

Essayer

methods(residuals)

qui répertorie, entre autres, "residuals.lm" et "residuals.glm". Cela signifie que lorsque vous avez ajusté un modèle linéaire, m et typeresiduals(m), residuals.lm sera appelé. Lorsque vous avez ajusté un modèle linéaire généralisé, residuals.glm sera appelé. C'est une sorte de modèle d'objet C ++ renversé. En C ++, vous définissez une classe de base ayant des fonctions virtuelles, qui sont remplacées par des classes dérivées. En R, vous définissez une fonction virtuelle (aka générique), puis vous décidez quelles classes remplaceront cette fonction (c'est-à-dire définir une méthode). Notez que les classes faisant cela n'ont pas besoin d'être dérivées d'une super-classe commune. Je ne serais pas d'accord pour préférer généralement S3 à S4. S4 a plus de formalisme (= plus de frappe) et cela peut être trop pour certaines applications. Cependant, les classes S4 peuvent être définies comme une classe ou une structure en C ++. Vous pouvez spécifier qu'un objet d'une certaine classe est composé d'une chaîne et de deux nombres par exemple:

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

Les méthodes appelées avec un objet de cette classe peuvent s'appuyer sur l'objet ayant ces membres. C'est très différent des classes S3, qui ne sont qu'une liste d'éléments.

Avec S3 et S4, vous appelez une fonction membre par fun(object, args)et non par object$fun(args). Si vous cherchez quelque chose comme ce dernier, jetez un œil au paquet proto.

Harald Brendel
la source
Je suis presque sûr que l'idée de fonctions membres et de méthodes appartenant à des objets n'a pas beaucoup de sens dans R. Les méthodes n'appartiennent pas aux objets (les fonctions sont également des objets) mais appartiennent à la fonction.
petermeissner
3

Voici un aperçu rapide mis à jour des nombreux systèmes d'objets R selon "Advanced R, 2nd edition" (CRC Press, 2019) par Hadley Wickham (Chief Scientist chez RStudio), qui a une représentation Web ici , basée sur le chapitre sur Object -Programmation orientée .

Couverture de livre Advanced R

La première édition de 2015 a une représentation Web ici , avec le chapitre correspondant sur OO ici .

Approches des systèmes OO

Hadley définit ce qui suit pour distinguer deux approches distinctes de la programmation OO:

POO fonctionnelle : les méthodes (morceaux de code appelables) appartiennent à des fonctions génériques (à ne pas confondre avec les méthodes génériques Java / C # ). Considérez les méthodes comme étant situées dans une table de recherche globale. La méthode à exécuter est trouvée par le système d'exécution en fonction du nom de la fonction et du type (ou de la classe d'objet) d'un ou plusieurs arguments passés à cette fonction (c'est ce qu'on appelle la «méthode de répartition»). Syntaxe-sage, les appels de méthode peut ressembler à des appels de fonctions ordinaires: myfunc(object, arg1, arg2). Cet appel conduirait le runtime à rechercher la méthode associée à la paire ("myfunc", typeof (object)) ou éventuellement ("myfunc", typeof (object), typeof (arg1), typeof (arg2))si la langue prend en charge cela. Dans S3 de R, le nom complet de la fonction générique donne la paire (nom-fonction, classe) . Par exemple: mean.Dateest la méthode pour calculer la moyenne des dates. Essayez methods("mean")de lister les méthodes génériques avec le nom de la fonction mean. L'approche fonctionnelle OOP se retrouve par exemple dans le pionnier OO Smalltalk , le Common Lisp Object System et Julia . Hadley note que "Par rapport à R, l'implémentation de Julia est entièrement développée et extrêmement performante."

POO encapsulée : les méthodes appartiennent à des objets ou à des classes, et les appels de méthode ressemblent généralement à object.method(arg1, arg2). Cela s'appelle encapsulé car l'objet encapsule à la fois les données (champs) et le comportement (méthodes). Considérez la méthode comme étant située dans une table de consultation attachée à l'objet ou à la description de classe de l'objet. Le runtime recherche la méthode en fonction du nom de la méthode et éventuellement du type d'un ou plusieurs arguments. C'est l'approche que l'on trouve dans les langages OO "populaires" comme C ++, Java, C #.

Dans les deux cas, si l'héritage est pris en charge (c'est probablement le cas), le moteur d'exécution peut parcourir la hiérarchie de classes vers le haut jusqu'à ce qu'il ait trouvé une correspondance pour la clé de recherche d'appel.

Comment savoir à quel système appartient un objet R

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

Les systèmes d'objets R

S3

  • Approche fonctionnelle de la POO.
  • Système le plus important selon Hadley.
  • Le plus simple, le plus courant. Premier système OO utilisé par R.
  • Livré avec la base R, utilisée dans toute la base R.
  • S'appuie sur des conventions plutôt que sur des garanties appliquées.
  • Voir Chambers, John M et Trevor J Hastie. 1992. "Statistical Models in S." Wadsworth & Brooks / Cole Advanced Books & Software.
  • Détails dans "Advanced R, 2e édition" ici .

S4

  • Approche fonctionnelle de la POO.
  • Troisième système le plus important selon Hadley.
  • Réécriture de S3, donc similaire à S3, mais plus formelle et plus stricte: cela vous oblige à réfléchir attentivement à la conception du programme. Convient pour la construction de grands systèmes (par exemple le projet Bioconductor ).
  • Implémenté dans le package de base "methods".
  • Voir: Chambers, John M. 1998. «Programming with Data: A Guide to the S Language». Springer.
  • Détails dans "Advanced R, 2e édition" ici .

RC aka "Classes de référence"

  • Approche POO encapsulée.
  • Livré avec la base R.
  • Basé sur S4.
  • Les objets RC sont des types spéciaux d'objets S4 qui sont également "mutables". c'est-à-dire qu'au lieu d'utiliser la sémantique habituelle de copie sur modification de R, ils peuvent être modifiés sur place. Notez que l'état mutable est difficile à raisonner et est une source de bugs horribles, mais peut conduire à un code plus efficace dans certaines applications.

R6

  • Approche POO encapsulée.
  • Deuxième système le plus important selon Hadley.
  • Peut être trouvé dans le package R6 (installer avec library(R6))
  • Similaire à RC, mais plus léger et beaucoup plus rapide: cela ne dépend pas de S4 ou du package de méthodes . Construit au-dessus des environnements R. A aussi:
    • méthodes publiques et privées
    • liaisons actives (champs, qui, lorsqu'ils sont accédés, appellent en fait une méthode)
    • héritage de classe qui fonctionne sur tous les packages
    • les deux méthodes de classe (code qui appartient à la classe et peut accéder à une instance via self, private, super) et les fonctions membres (fonctions assignées aux champs, mais qui ne sont pas seulement les méthodes, fonctions)
  • Fournit un moyen standardisé d'échapper à la sémantique de «copie sur modification» de R
  • Voir le site du package: "R6: Programmation orientée objet encapsulée pour R" .
  • Détails dans "Advanced R, 2e édition" ici .

Autres

Il y en a d'autres, comme R.oo (similaire à RC), proto (basé sur un prototype, pensez JavaScript) et Mutatr . Cependant, "Advanced R" dit:

Hormis le R6, qui est largement utilisé, ces systèmes présentent avant tout un intérêt théorique. Ils ont leurs points forts, mais peu d'utilisateurs de R les connaissent et les comprennent, il est donc difficile pour les autres de lire et de contribuer à votre code.

N'oubliez pas de lire également le chapitre sur les compromis dans "Advanced R, 2nd edition" .

David Tonhofer
la source