Che cosa significa "metodi S3" in R?


124

Dato che sono abbastanza nuovo su R, non so quali siano i metodi e gli oggetti S3. Ho scoperto che ci sono sistemi di oggetti S3 e S4 e alcuni raccomandano di utilizzare S3 su S4 se possibile (vedi la Guida allo stile R di Google su http://google-styleguide.googlecode.com/svn/trunk/google-r-style. html ) *. Tuttavia, non conosco la definizione esatta di metodi / oggetti S3.

Aggiornamento: A partire dal 2019, di Google Guida R Style collegamento ipertestuale è ora qui .

Risposte:


85

La maggior parte delle informazioni rilevanti può essere trovata guardando ?S3o ?UseMethod, in breve:

S3 si riferisce a uno schema di dispacciamento del metodo. Se hai utilizzato R per un po ', si noterà che ci sono print, predicte summarymetodi per un sacco di diversi tipi di oggetti.

In S3, funziona con:

  • impostazione della classe di oggetti di interesse (ad es .: il valore restituito di una chiamata al metodo glmha classe glm)
  • fornire un metodo con il nome generale (ad esempio print), allora un punto, e quindi il nome classe (es: print.glm)
  • un po 'di preparazione deve essere stata fatta a questo nome generale ( print) per farlo funzionare, ma se stai semplicemente cercando di conformarti ai nomi dei metodi esistenti, non hai bisogno di questo (vedi l'aiuto a cui mi riferivo prima se lo fai ).

Agli occhi di chi guarda, e in particolare all'utente del pacchetto di montaggio del modello funky appena creato, è molto più comodo poter digitare predict(myfit, type="class")di predict.mykindoffit(myfit, type="class").

C'è molto di più, ma questo dovrebbe iniziare. Ci sono alcuni svantaggi in questo modo di dispacciare metodi basati su un attributo (classe) di oggetti (e i puristi C probabilmente si svegliano di notte inorriditi), ma per molte situazioni, funziona in modo decente. Con l'attuale versione di R, sono stati implementati modi più recenti (S4 e classi di riferimento), ma la maggior parte delle persone usa (solo) S3.


54

Per iniziare con S3, guarda il codice per la medianfunzione. Digitando medianal prompt dei comandi si rivela che ha una riga nel suo corpo, vale a dire

UseMethod("median")

Ciò significa che è un metodo S3. In altre parole, puoi avere una medianfunzione diversa per diverse classi S3. Per elencare tutti i possibili metodi mediani, digitare

methods(median) #actually not that interesting.  

In questo caso, esiste solo un metodo, il valore predefinito, che viene chiamato per qualsiasi cosa. Puoi vedere il codice digitando

median.default

Un esempio molto più interessante è la printfunzione, che ha molti metodi diversi.

methods(print)  #very exciting

Si noti che alcuni dei metodi sono *accanto al loro nome. Ciò significa che sono nascosti all'interno dello spazio dei nomi di alcuni pacchetti. Utilizzare findper scoprire in quale pacchetto si trovano. Ad esempio

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

39

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

I tre sistemi OO di R differiscono nel modo in cui sono definiti classi e metodi:

  • S3 implementa uno stile di programmazione OO chiamato OO a funzioni generiche. Questo è diverso dalla maggior parte dei linguaggi di programmazione, come Java, C ++ e C #, che implementano OO che passa messaggi. Con il passaggio dei messaggi, i messaggi (metodi) vengono inviati agli oggetti e l'oggetto determina quale funzione chiamare. In genere, questo oggetto ha un aspetto speciale nella chiamata al metodo, di solito appare prima del nome del metodo / messaggio: ad esempio canvas.drawRect ("blu"). S3 è diverso. Mentre i calcoli vengono ancora eseguiti tramite metodi, uno speciale tipo di funzione chiamata funzione generica decide quale metodo chiamare, ad es. DrawRect (canvas, "blue"). S3 è un sistema molto casual. Non ha una definizione formale di classi.

  • S4 funziona in modo simile a S3, ma è più formale. Ci sono due principali differenze con S3. S4 ha definizioni di classe formali, che descrivono la rappresentazione e l'ereditarietà per ogni classe e ha funzioni speciali di supporto per la definizione di generici e metodi. S4 ha anche un invio multiplo, il che significa che le funzioni generiche possono scegliere metodi basati sulla classe di qualsiasi numero di argomenti, non solo uno.

  • Le classi di riferimento, chiamate RC in breve, sono abbastanza diverse da S3 e S4. RC implementa OO che passa messaggi, quindi i metodi appartengono alle classi, non alle funzioni. $ viene utilizzato per separare oggetti e metodi, quindi le chiamate ai metodi sembrano canvas $ drawRect ("blu"). Anche gli oggetti RC sono mutabili: non usano la solita semantica di R su copia-modifica, ma vengono modificati in posizione. Ciò li rende più difficili da ragionare, ma consente loro di risolvere problemi che sono difficili da risolvere con S3 o S4.

C'è anche un altro sistema che non è proprio OO, ma è importante menzionare qui:

  • tipi di base, i tipi di livello C interni che sono alla base degli altri sistemi OO. I tipi di base sono per lo più manipolati utilizzando il codice C, ma sono importanti da sapere perché forniscono i mattoni per gli altri sistemi OO.

11

Sono arrivato a questa domanda principalmente chiedendomi da dove provenissero i nomi. Da questo articolo di Wikipedia sembra che il nome si riferisca alla versione del linguaggio di programmazione S su cui si basa R. Gli schemi di dispacciamento del metodo descritti nelle altre risposte provengono da S e sono etichettati in modo appropriato in base alla versione.


10

Provare

methods(residuals)

che elenca, tra gli altri, "residuals.lm" e "residuals.glm". Ciò significa che dopo aver montato un modello lineare, m e un tiporesiduals(m), residuals.lm verrà chiamato. Dopo aver montato un modello lineare generalizzato, verrà chiamato residuals.glm. È una specie di modello a oggetti C ++ capovolto. In C ++, si definisce una classe base con funzioni virtuali, che vengono sovrascritte da classi derivate. In R definisci una funzione virtuale (aka generico) e poi decidi quali classi sovrascriveranno questa funzione (aka definiscono un metodo). Notare che le classi che lo fanno non devono essere derivate da una superclasse comune. Non accetterei di preferire generalmente S3 rispetto a S4. S4 ha più formalismo (= più digitazione) e questo potrebbe essere troppo per alcune applicazioni. Le classi S4, tuttavia, possono essere definite come una classe o struttura in C ++. È possibile specificare che un oggetto di una determinata classe è costituito da una stringa e due numeri, ad esempio:

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

I metodi chiamati con un oggetto di quella classe possono fare affidamento sull'oggetto con quei membri. È molto diverso dalle classi S3, che sono solo un elenco di un gruppo di elementi.

Con S3 e S4, chiamate una funzione membro per fun(object, args)e non per object$fun(args). Se stai cercando qualcosa come quest'ultimo, dai un'occhiata al pacchetto proto.


Sono abbastanza sicuro che l'idea delle funzioni membro e dei metodi appartenenti agli oggetti non abbia molto senso in R. I metodi non appartengono agli oggetti (anche le funzioni sono anche oggetti) ma appartengono alla funzione.
petermeissner,

3

Ecco un aggiornato rapida carrellata dei numerosi sistemi a oggetti R secondo il "Advanced R, 2nd edition" (CRC Press, 2019) da Hadley Wickham (Chief Scientist presso RStudio), che ha una rappresentazione web qui , sulla base del capitolo su Object Programmazione orientata .

Copertina di libro R avanzata

La prima edizione del 2015 ha una rappresentazione web qui , con il capitolo corrispondente su OO qui .

Approcci ai sistemi OO

Hadley definisce quanto segue per distinguere due approcci distinti alla programmazione OO:

OOP funzionale : i metodi (parti di codice richiamabili) appartengono a funzioni generiche (da non confondere con i metodi generici Java / C # ). Pensa ai metodi come situati in una tabella di ricerca globale. Il metodo da eseguire è trovato dal sistema di runtime in base al nome della funzione e al tipo (o classe oggetto) di uno o più argomenti passati a quella funzione (questo è chiamato "invio del metodo"). Sintassi-saggio, le chiamate di metodo può apparire come normali chiamate di funzione: myfunc(object, arg1, arg2). Questa chiamata indurrebbe il runtime a cercare il metodo associato alla coppia ("myfunc", typeof (oggetto)) o eventualmente ("myfunc", tipoof (oggetto), tipoof (arg1), tipoof (arg2))se la lingua lo supporta. In S3 di R, il nome completo della funzione generica fornisce la coppia (nome-funzione, classe) . Ad esempio: mean.Dateè il metodo per calcolare la media di Date. Prova methods("mean")a elencare i metodi generici con il nome della funzione mean. L'approccio OOP funzionale si trova ad esempio nel pioniere OO Smalltalk , Common Lisp Object System e Julia . Hadley osserva che "Rispetto a R, l'implementazione di Julia è completamente sviluppata ed estremamente performante".

OOP incapsulato : i metodi appartengono a oggetti o classi e in genere le chiamate ai metodi sembrano simili object.method(arg1, arg2). Questo si chiama incapsulato perché l'oggetto incapsula sia i dati (campi) sia il comportamento (metodi). Pensa al metodo come a una tabella di ricerca collegata all'oggetto o alla descrizione della classe dell'oggetto. Il runtime cerca il metodo in base al nome del metodo e possibilmente al tipo di uno o più argomenti. Questo è l'approccio trovato nei linguaggi OO "popolari" come C ++, Java, C #.

In entrambi i casi, se l'ereditarietà è supportata (probabilmente lo è), il runtime può attraversare la gerarchia di classi verso l'alto fino a quando non trova una corrispondenza per la chiave di ricerca della chiamata.

Come scoprire a quale sistema appartiene un oggetto R

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

I sistemi di oggetti R.

S3

  • Approccio OOP funzionale.
  • Il sistema più importante secondo Hadley.
  • Più semplice, più comune. Primo sistema OO utilizzato da R.
  • Viene fornito con la base R, utilizzata in tutta la base R.
  • Si affida a convenzioni anziché a garanzie applicate.
  • Vedi Chambers, John M e Trevor J Hastie. 1992. "Modelli statistici a S." Libri e software avanzati Wadsworth & Brooks / Cole.
  • Dettagli in "Advanced R, 2nd edition" qui .

S4

  • Approccio OOP funzionale.
  • Terzo sistema più importante secondo Hadley.
  • Riscrivi S3, quindi simile a S3, ma più formale e più rigoroso: ti costringe a pensare attentamente alla progettazione del programma. Adatto per la costruzione di grandi sistemi (ad esempio il progetto Bioconductor ).
  • Implementato nel pacchetto "metodi" di base.
  • Vedi: Chambers, John M. 1998. "Programmazione con dati: una guida al linguaggio S." Springer.
  • Dettagli in "Advanced R, 2nd edition" qui .

RC aka "Classi di riferimento"

  • Approccio OOP incapsulato.
  • Viene fornito con base R.
  • Basato su S4.
  • Gli oggetti RC sono tipi speciali di oggetti S4 che sono anche "mutabili". cioè invece di usare la solita semantica di copia su modifica di R, possono essere modificati sul posto. Si noti che lo stato mutevole è difficile da ragionare e una fonte di brutti bug ma può portare a un codice più efficiente in alcune applicazioni.

R6

  • Approccio OOP incapsulato.
  • Secondo sistema più importante secondo Hadley.
  • Può essere trovato nel pacchetto R6 (installa con library(R6))
  • Simile a RC, ma più leggero e molto più veloce: non dipende da S4 o dal pacchetto metodi . Costruito su ambienti R. Ha anche:
    • metodi pubblici e privati
    • associazioni attive (campi che, quando vi si accede, chiamano effettivamente un metodo)
    • eredità di classe che funziona su tutti i pacchetti
    • entrambi i metodi di classe (codice che appartiene alla classe e possono accedere un'istanza via self, private, super) e funzioni membro (funzioni assegnate ai campi, ma che non sono metodi, come funzioni)
  • Fornisce un modo standardizzato per sfuggire alla semantica di "copia su modifica" di R
  • Vedere il sito del pacchetto: "R6: programmazione incapsulata orientata agli oggetti per R" .
  • Dettagli in "Advanced R, 2nd edition" qui .

Altri

Ce ne sono altri, come R.oo (simile a RC), proto (basato su prototipo, pensa JavaScript) e Mutatr . Tuttavia, "Advanced R" dice:

Oltre a R6, che è ampiamente utilizzato, questi sistemi sono principalmente di interesse teorico. Hanno i loro punti di forza, ma pochi utenti R li conoscono e li capiscono, quindi è difficile per gli altri leggere e contribuire al tuo codice.

Leggi anche il capitolo sui compromessi in "Advanced R, 2nd edition" .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.