2015-12-01 22 views
14

Próbuję napisać metodę rbind dla konkretnej klasy. Oto prosty przykład, w którym to nie działa (przynajmniej dla mnie):S3 wysyłanie `rbind` i` cbind`

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

Po wprowadzeniu tej funkcji, to pozornie może potwierdzić, że jest to ważna metoda R wie o:

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

jednak nie są ujmowane, gdy próbuję go użyć:

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

strona help mówi, że wysyłka odbywa się wewnętrznie w sposób następujący:

  1. Dla każdego argumentu otrzymujemy listę możliwych przynależności do klasy od atrybutu klasy.
  2. Sprawdzamy każdą klasę po kolei, aby sprawdzić, czy istnieje stosowna metoda .
  3. Jeśli znajdziemy odpowiednią metodę, upewnimy się, że jest ona identyczna z dowolną metodą określoną dla poprzednich argumentów. Jeśli jest identyczny, kontynuujemy, kontynuujemy, w przeciwnym razie natychmiast przechodzimy do domyślnego kodu.

Dzięki rbind("abc", "xyz") uważam, że wszystkie te kryteria są spełnione. Co daje i jak mogę to naprawić?

+2

Zobacz '? InternalMethods', a także coś podobnego do' x = "abc"; y = "xyz"; is.object (x) || is.object (y); rbind (x, y); attr (x, "class") = "character"; attr (y, "class") = "character"; is.object (x) || is.object (y); rbind (x, y) ' –

Odpowiedz

9
attributes("abc") 
#NULL 

Wektor character nie ma atrybutu klasy. Nie sądzę, aby można było wywołać metodę rbind dla niejawnych klas.

+0

Co z' class ("abc") # [1] "character" '? – thothal

+2

Wydaje się być mylącym, że 'class (" abc ")' to '" character "'. –

+5

To niejawna klasa. Wywołanie metody rbind sprawdza tylko atrybuty klasy, czyli jawne klasy. – Roland

3

Rozwiązaniem byłoby zdefiniować własną klasę:

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

Powodem dlaczego to nie działa z character był ładnie wyjaśnione przez Roland w swoim komentarzu.

+1

Możesz także pracować z "znakami", jeśli określisz "b" "znak" jako klasę obiektu: 'attributes (b) = list (class =" character "); rbind (b, b) ' –

1

rbind nie jest standardową funkcją S3, więc nie można jej "przechwycić" dla character.

Na szczęście można zastąpić domyślną implementację. Wypróbuj:

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(...) 
    } 
} 

Zasadniczo sprawdzamy, czy wszystkie argumenty są znakami. Jeśli tak, nazywamy naszą funkcję znaku. Jeśli nie, wywołujemy domyślną implementację.

Powiązane problemy