O que "métodos S3" significa em R?

124

Como sou bastante novo no R, não sei quais são os métodos e objetos do S3. Descobri que existem sistemas de objetos S3 e S4 e alguns recomendam o uso do S3 sobre S4, se possível (consulte o Guia de estilo R do Google em http://google-styleguide.googlecode.com/svn/trunk/google-r-style. html ) *. No entanto, não sei a definição exata dos métodos / objetos do S3.

Atualização: A partir de 2019, o hiperlink R Style Guide do Google está aqui .

jiggysoo
fonte

Respostas:

85

A maioria das informações relevantes pode ser encontrada olhando para , ?S3ou ?UseMethodem poucas palavras:

S3 refere-se a um esquema de envio de método. Se você já usou R por um tempo, você vai notar que existem print, predicte summarymétodos para uma série de diferentes tipos de objetos.

No S3, isso funciona por:

  • definir a classe de objetos de interesse (por exemplo: o valor de retorno de uma chamada ao método glmpossui classe glm)
  • proporcionando um método com o nome geral (por exemplo print), então um ponto, e depois o nome de classe (por exemplo: print.glm)
  • alguma preparação deve ter sido feita para esse nome geral ( print) para que isso funcione, mas se você está simplesmente procurando se adaptar aos nomes de métodos existentes, não precisa disso (consulte a ajuda a que me referi anteriormente, se precisar )

Para os olhos de quem vê e, principalmente, do usuário do seu novo pacote de encaixe de modelos, é muito mais conveniente digitar do predict(myfit, type="class")que predict.mykindoffit(myfit, type="class").

Há um pouco mais, mas isso deve ajudá-lo a começar. Existem algumas desvantagens nessa maneira de despachar métodos com base em um atributo (classe) de objetos (e os puristas C provavelmente ficam acordados à noite, horrorizados com isso), mas, em muitas situações, funciona decentemente. Com a versão atual do R, novas formas foram implementadas (S4 e classes de referência), mas a maioria das pessoas ainda (apenas) usa o S3.

Nick Sabbe
fonte
54

Para começar com o S3, observe o código da medianfunção. Digitar medianno prompt de comando revela que ele possui uma linha no corpo, a saber

UseMethod("median")

Isso significa que é um método S3. Em outras palavras, você pode ter uma medianfunção diferente para diferentes classes S3. Para listar todos os métodos medianos possíveis, digite

methods(median) #actually not that interesting.  

Nesse caso, há apenas um método, o padrão, que é chamado para qualquer coisa. Você pode ver o código para isso digitando

median.default

Um exemplo muito mais interessante é a printfunção, que possui muitos métodos diferentes.

methods(print)  #very exciting

Observe que alguns dos métodos têm *s ao lado do nome. Isso significa que eles estão ocultos dentro do namespace de algum pacote. Use findpara descobrir em qual pacote eles estão. Por exemplo

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

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

Os três sistemas OO de R diferem em como as classes e métodos são definidos:

  • O S3 implementa um estilo de programação OO chamado função OO genérica. Isso é diferente da maioria das linguagens de programação, como Java, C ++ e C #, que implementam OO de passagem de mensagens. Com a passagem de mensagens, as mensagens (métodos) são enviadas aos objetos e o objeto determina qual função chamar. Normalmente, esse objeto tem uma aparência especial na chamada do método, geralmente aparecendo antes do nome do método / mensagem: por exemplo, canvas.drawRect ("blue"). S3 é diferente. Enquanto os cálculos ainda são realizados por métodos, um tipo especial de função chamado função genérica decide qual método chamar, por exemplo, drawRect (canvas, "blue"). S3 é um sistema muito casual. Não possui definição formal de classes.

  • O S4 funciona de maneira semelhante ao S3, mas é mais formal. Existem duas grandes diferenças no S3. O S4 possui definições formais de classe, que descrevem a representação e herança de cada classe, e possui funções auxiliares especiais para definir genéricos e métodos. O S4 também possui vários despachos, o que significa que funções genéricas podem escolher métodos com base na classe de qualquer número de argumentos, não apenas um.

  • As classes de referência, chamadas de RC para abreviar, são bem diferentes de S3 e S4. O RC implementa OO que passa mensagens, portanto os métodos pertencem a classes, não a funções. $ é usado para separar objetos e métodos; portanto, as chamadas de método se parecem com canvas $ drawRect ("blue"). Os objetos RC também são mutáveis: eles não usam a semântica usual de copiar na modificação de R, mas são modificados no local. Isso os torna mais difíceis de raciocinar, mas permite resolver problemas difíceis de resolver com o S3 ou o S4.

Há também um outro sistema que não é exatamente OO, mas é importante mencionar aqui:

  • tipos de base, os tipos internos de nível C subjacentes aos outros sistemas OO. Os tipos de base são manipulados principalmente usando o código C, mas são importantes sobre o conhecimento, pois fornecem os blocos de construção para os outros sistemas OO.
Amit K Thakur
fonte
11

Cheguei a esta pergunta perguntando-me principalmente de onde os nomes vieram. Parece neste artigo da Wikipedia que o nome se refere à versão da linguagem de programação S na qual R se baseia. Os esquemas de envio de métodos descritos nas outras respostas vêm de S e são rotulados de acordo com a versão.

Jonathan Adelson
fonte
10

Experimentar

methods(residuals)

que lista, entre outros, "residuals.lm" e "residuals.glm". Isso significa que quando você ajustou um modelo linear, m e tiporesiduals(m), residuals.lm será chamado. Quando você ajustar um modelo linear generalizado, residuals.glm será chamado. É o tipo de modelo de objeto C ++ virado de cabeça para baixo. No C ++, você define uma classe base com funções virtuais, que são substituídas por classes derivadas. Em R, você define uma função virtual (também conhecida como genérica) e depois decide quais classes substituirão essa função (também conhecida como definir um método). Observe que as classes que fazem isso não precisam ser derivadas de uma superclasse comum. Eu não concordaria em preferir S3 a S4. O S4 possui mais formalismo (= mais digitação) e isso pode ser demais para alguns aplicativos. As classes S4, no entanto, podem ser definidas como uma classe ou estrutura em C ++. Você pode especificar que um objeto de uma determinada classe seja constituído por uma sequência e dois números, por exemplo:

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

Os métodos chamados com um objeto dessa classe podem confiar no objeto que possui esses membros. Isso é muito diferente das classes S3, que são apenas uma lista de vários elementos.

Com S3 e S4, você chama uma função de membro por fun(object, args)e não por object$fun(args). Se você está procurando algo parecido com o último, dê uma olhada no pacote proto.

Harald Brendel
fonte
Tenho certeza de que a idéia de funções-membro e métodos pertencentes a objetos não faz muito sentido em R. Métodos não pertencem a objetos (também funções também são objetos), mas pertencem à função.
Petermeissner
3

Aqui está um resumo rápido e atualizado dos inúmeros sistemas de objetos R de acordo com "Advanced R, 2nd edition" (CRC Press, 2019) de Hadley Wickham (cientista-chefe do RStudio), que possui uma representação na Web aqui , com base no capítulo sobre Objeto Programação orientada .

Capa do livro Advanced R

A primeira edição de 2015 tem uma representação na Web aqui , com o capítulo correspondente sobre OO aqui .

Abordagens para sistemas OO

Hadley define o seguinte para distinguir duas abordagens distintas da programação OO:

OOP funcional : métodos (partes de código que podem ser chamadas) pertencem a funções genéricas (não devem ser confundidas com métodos genéricos Java / C # ). Pense nos métodos como estando localizados em uma tabela de pesquisa global. O método a ser executado é encontrado pelo sistema de tempo de execução com base no nome da função e no tipo (ou classe de objeto) de um ou mais argumentos passados ​​para essa função (isso é chamado de "despacho de método"). Sintaxe-wise, chamadas de método pode ser parecido com chamadas de funções comuns: myfunc(object, arg1, arg2). Essa chamada levaria o tempo de execução a procurar o método associado ao par ("myfunc", typeof (objeto)) ou possivelmente ("myfunc", typeof (objeto), typeof (arg1), typeof (arg2))se o idioma suportar isso. No S3 de R, o nome completo da função genérica fornece o par (nome da função, classe) . Por exemplo: mean.Dateé o método para calcular a média de datas. Tente methods("mean")listar os métodos genéricos com o nome da função mean. A abordagem OOP Funcional é encontrada, por exemplo, no pioneiro OO Smalltalk , no Common Lisp Object System e Julia . Hadley observa que "Em comparação com R, a implementação de Julia é totalmente desenvolvida e extremamente eficiente".

OOP encapsulado : os métodos pertencem a objetos ou classes e as chamadas de método geralmente se parecem object.method(arg1, arg2). Isso é chamado de encapsulado porque o objeto encapsula dados (campos) e comportamento (métodos). Pense no método como estando localizado em uma tabela de pesquisa anexada ao objeto ou à descrição da classe do objeto. O tempo de execução procura o método com base no nome do método e possivelmente no tipo de um ou mais argumentos. Essa é a abordagem encontrada em linguagens OO "populares", como C ++, Java, C #.

Nos dois casos, se a herança for suportada (provavelmente é), o tempo de execução poderá percorrer a hierarquia da classe para cima até encontrar uma correspondência para a chave de pesquisa de chamada.

Como descobrir a qual sistema um objeto R pertence

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

Os sistemas de objetos R

S3

  • Abordagem funcional de POO.
  • Sistema mais importante de acordo com Hadley.
  • Mais simples, mais comum. Primeiro sistema OO usado por R.
  • Vem com a base R, usada em toda a base R.
  • Baseia-se em convenções e não em garantias impostas.
  • Veja Chambers, John M e Trevor J. Hastie. 1992. "Modelos estatísticos em S." Wadsworth & Brooks / Cole Advanced Books & Software.
  • Detalhes em "Advanced R, 2nd edition" aqui .

S4

  • Abordagem funcional de POO.
  • Terceiro sistema mais importante de acordo com Hadley.
  • Reescreva o S3, portanto, semelhante ao S3, mas mais formal e mais rigoroso: obriga você a pensar cuidadosamente sobre o design do programa. Adequado para a construção de grandes sistemas (por exemplo, o projeto Bioconductor ).
  • Implementado no pacote "métodos" base.
  • Veja: Chambers, John M. 1998. "Programação com dados: um guia para a linguagem S." Springer.
  • Detalhes em "Advanced R, 2nd edition" aqui .

RC aka "Classes de referência"

  • Abordagem OOP encapsulada.
  • Vem com a base R.
  • Baseado em S4.
  • Objetos RC são tipos especiais de objetos S4 que também são "mutáveis". ou seja, em vez de usar a semântica usual de copiar na modificação de R, eles podem ser modificados no local. Observe que é difícil argumentar sobre o estado mutável e uma fonte de erros feios, mas pode levar a um código mais eficiente em certos aplicativos.

R6

  • Abordagem OOP encapsulada.
  • Segundo sistema mais importante de acordo com Hadley.
  • Pode ser encontrado no pacote R6 (instale com library(R6))
  • Semelhante ao RC, mas mais leve e muito mais rápido: não depende do S4 ou do pacote de métodos . Construído em cima de ambientes R. Também tem:
    • métodos públicos e privados
    • ligações ativas (campos que, quando acessados, na verdade chamam um método)
    • herança de classe que funciona em pacotes
    • ambos os métodos de classe (código que pertence a classe e pode acessar uma instância via self, private, super) e funções de membro (funções atribuídas aos campos, mas que não são métodos, apenas funções)
  • Fornece uma maneira padronizada de escapar da semântica "copiar para modificar" de R
  • Veja o site do pacote: "R6: Programação orientada a objetos encapsulada para R" .
  • Detalhes em "Advanced R, 2nd edition" aqui .

Outras

Existem outros, como R.oo (semelhante ao RC), proto (baseado em protótipo, pense em JavaScript) e Mutatr . No entanto, "Advanced R" diz:

Além do R6, que é amplamente utilizado, esses sistemas são principalmente de interesse teórico. Eles têm seus pontos fortes, mas poucos usuários de R os conhecem e entendem, portanto é difícil para outros lerem e contribuírem para o seu código.

Leia também o capítulo sobre trade-offs em "Advanced R, 2nd edition" .

David Tonhofer
fonte