2016-09-23 7 views
3

Ich habe eine S4-Klasse entwickelt, die im Wesentlichen ein data.frame mit ein wenig zusätzlichen Informationen ist. Für die Zwecke dieser Frage sind die "zusätzlichen" Merkmale dieser Klasse irrelevant. Entscheidend ist, dass die Klasse ein data.frame-Objekt enthält, das in einem der Slots gespeichert ist. (Ich habe den data.frame in einen Slot eingefügt, anstatt ihn als Superklasse zu bezeichnen, weil ich finde, dass S4-Klassen, die data.frames enthalten, aus irgendeinem Grund die data.frames zu Listen machen).R: jede Funktion ändern, die auf eine S4-Klasse angewendet wird

Hier ist ein einfaches Beispiel:

setClass('tmp_class', slots = c(df = 'data.frame')) 

test_object <- new('tmp_class', df = data.frame(Num = 1:10, Let = letters[1:10])) 

Nun, was ich möchte ist, es zu tun, so dass im Wesentlichen jede Funktion auf ein Objekt dieser Klasse, die auf die data.frame in Schlitz aufgebracht wird @df. Es ist einfach, Methoden zu schreiben für bestimmte Funktionen, dies zu tun, wie:

setMethod('dim', signature = c(x = 'tmp_class'), function(x) dim([email protected])) 

Aber ich bin beschränkt sich auf nur die Funktionen der ich denken kann, und jede Funktion von einem Benutzer erfunden würde nicht funktionieren.

Es ist eine einfache Sache, eine Art Wrapper/Verschluss zu schreiben, eine Funktion ändern auf meiner Klasse zu arbeiten, wie folgt aus:

tmp_classize <- function(func){ 
    function(tmp, ...){ func([email protected], ...) } 
} 

Also, anstatt Methoden zum Schreiben von, sagen wir, COLNAMES() oder ncol(), konnte ich nur laufen:

tmp_classize(colnames)(test_object) 

oder

tmp_classize(ncol)(test_object) 

Aber was ich möchte zu tun, so mehow evoze meine "tmp_classize" -Funktion auf jede Funktion automatisch auf meine Klasse angewendet. Ich kann nicht herausfinden, wie es geht. Ich dachte, wenn ich irgendwie eine "universelle Methode" mit einer Eingabesignatur der Klasse "tmp_class" aufrufen könnte und dann sys.function() verwenden würde, um die tatsächlich aufgerufene Funktion zu holen, könnte ich vielleicht etwas machen, aber A) dort sind Rekursionsprobleme B) Ich weiß nicht wie ich eine solche "universelle" Methode nennen soll. Es scheint mir, dass die Lösung, wenn sie überhaupt existiert, eine nicht-standardmäßige Bewertung erforderlich machen könnte, die ich eher vermeiden, aber gegebenenfalls anwenden könnte.

Danke!

P.S. Ich bin mir bewusst, dass dieses Unterfangen eine unkluge/schlechte Programmiertechnik ist, und ich werde es vielleicht nie wirklich in einem Paket implementieren. Trotzdem bin ich neugierig zu wissen, ob es möglich ist.

P.P.S. Ich würde mich auch für die gleiche Idee interessieren, die auf S3-Klassen angewendet wird!

Antwort

0

Grundsätzlich, was Sie tun können, ist ein classUnion für Ihre Klasse machen und data.frame und Schreibmethoden für Ihre Klasse, die mit all den Möglichkeiten beschäftigen, lesen und schreiben zu data.frames wie $, [, dim(), <- und vieles mehr . Wenn andere Funktionen versuchen, Ihre neue Klasse als data.frame zu verwenden, gibt es Methoden dafür. Dies wird in John Chambers "Software for Data Analysis" ab Seite 375 etwas erklärt. Dieses System ist jedoch möglicherweise nur schwer zu implementieren.

Ein einfacheres System kann sein, einfach ein zusätzliches Attribut zu Ihrem data.frame mit den zusätzlichen Informationen hinzuzufügen, die Sie benötigen.Zum Beispiel:

x<-data.frame(a=1:3,b=4:6) 
attr(x,"Info")<-"Extra info I need" 
attributes(x)$Info 
[1] "Extra info I need" 

ist dies nicht so elegant wie eine S4 Klasse aber wird alles tun, ein data.frame tut. Ich vermute, dass jemand, der mit S3 Klassen vertraut ist, diese Idee ein wenig verbessern könnte.

0

Die einfachste Lösung ist, dass Ihre Klasse data.frame enthält anstatt sie als einen der Steckplätze zu haben. Zum Beispiel ist hier ein data.frame mit einem Zeitstempel:

setclass(
    "timestampedDF", 
    slots=c(timestamp="POSIXt"), 
    contains="data.frame" 
) 

Nun sind alle Funktionen, die Arbeit für eine data.frame (wie head) timestampedDF Objekte automatisch funktionieren. Wenn Sie auf den "Datenrahmenteil" zugreifen müssen, wird dieser in einem versteckten Steckplatz [email protected] gehalten.

Verwandte Themen