Frage S3-Versand von `rbind` und` cbind`


Ich versuche ein zu schreiben rbind Methode für eine bestimmte Klasse. Hier ist ein einfaches Beispiel, wo es nicht funktioniert (zumindest für mich):

rbind.character <- function(...) {
    do.call("paste", list(...))
}

Nachdem ich diese Funktion eingegeben habe, kann ich bestätigen, dass es eine gültige Methode ist, die R kennt:

> methods("rbind")
[1] rbind.character  rbind.data.frame rbind.rootogram* rbind.zoo*      
see '?methods' for accessing help and source code

Es wird jedoch nicht erkannt, wenn ich versuche, es zu benutzen:

> rbind("abc", "xyz")
     [,1] 
[1,] "abc"
[2,] "xyz"
> #### compared with ####
> rbind.character("abc", "xyz")
[1] "abc xyz"

Die Hilfeseite sagt, dass der Versand intern wie folgt durchgeführt wird:

  1. Für jedes Argument erhalten wir die Liste der möglichen Klassenmitgliedschaften von das Klassenattribut
  2. Wir überprüfen jede Klasse der Reihe nach, um zu sehen, ob es ein anwendbares gibt Methode.
  3. Wenn wir eine anwendbare Methode finden, stellen wir sicher, dass sie identisch ist jede für frühere Argumente bestimmte Methode. Wenn es identisch ist, wir Weiter geht es, ansonsten fallen wir sofort auf den Standardcode.

Mit rbind("abc", "xyz")Ich glaube, dass all diese Kriterien erfüllt sind. Was gibt und wie kann ich es beheben?


14
2017-12-01 15:58


Ursprung


Antworten:


attributes("abc")
#NULL

EIN character Vektor hat kein Klassenattribut. Ich denke nicht, dass eine Methode von versendet werden kann rbind für die impliziten Klassen.


9
2017-12-01 16:10



Ein Workaround wäre, eine eigene Klasse zu definieren:

b <- "abc"
class(b) <- "mycharacter"
rbind.mycharacter <- function(...) {
   do.call("paste", list(...))
}
rbind(b, b)
# [1] "abc abc"

Der Grund, warum es nicht funktioniert character wurde von Roland in seinem Kommentar schön erklärt.


3
2017-12-01 16:14



rbind ist keine Standard-S3-Funktion, Sie können sie also nicht "abfangen" character.

Glücklicherweise können Sie die Standardimplementierung überschreiben. Versuchen:

rbind.character <- function(...) {

  print("hello from rbind.character")
}

rbind <- function(...) {

  args <- list(...)

  if (all(vapply(args, is.character, logical(1)))) {

    rbind.character(...)
  } else {

    base::rbind(...)
  }
}

Grundsätzlich überprüfen wir, ob die Argumente alle Zeichen sind. Wenn ja, rufen wir unsere Charakterfunktion auf. Wenn nicht, rufen wir die Standardimplementierung auf.


1
2017-12-01 16:38