2014-08-29 2 views
12

In Perl (und wahrscheinlich anderen Sprachen) können Sie eine Variable "binden", um das integrierte Verhalten durch ein benutzerdefiniertes Verhalten zu ersetzen. Zum Beispiel kann eine Hash-Tabelle mit benutzerdefinierten "Get" - und "Fetch" -Subroutinen verknüpft werden, die beispielsweise BerkeleyDB abfragen, so dass Daten persistent und nicht durch RAM begrenzt sind, aber immer noch wie normaler Hash für Perl aussehen und sich verhalten.Können Sie eine data.frame in R "binden" oder eine alternative Implementierung bereitstellen?

Ist etwas Ähnliches mit R möglich? Insbesondere habe ich gedacht, da eine data.frame sieht aus wie eine Tabelle in einer relationalen db, dass, wenn eine data.frame an etwas wie SQLite gebunden wäre, würde es R ermöglichen, sehr große Datenrahmen zu behandeln (Ich habe 100GB + in SQLite gestopft) ohne irgendwelche Codeänderungen.

+2

Try Paket 'sqldf' für Ihr eigentliches Problem, aber ich denke, was Sie vorschlagen, der S3-Klasse-Mechanismus ist. – James

+1

überprüfen Sie die Pakete "ff" und "ffbase", sie sind auf genau diesem Prinzip aufgebaut. –

+4

'data.table' und' dplyr's neues 'tbl_ *' ebenfalls – hrbrmstr

Antwort

2

Wie die Kommentare zeigen, wurde bereits eine Handvoll Paket auf dieser Idee (oder ähnlich) aufgebaut.

data.table und dplyr sind außergewöhnlich gut im Umgang mit sehr großen Daten.frame und Abfragen von ihnen. Wenn data.frame tatsächlich> 100GB ist, würde ich eher data.table empfehlen, die dplyr im Limit nrow-> Inf zu übertreffen scheint. Beide haben eine ausgezeichnete Unterstützung bei stackoverflow, wenn Sie es brauchen.

Allerdings, um Ihre Frage tatsächlich zu beantworten (und um für die zukünftigen Leser dieser Frage nützlich zu sein): ja ist es möglich, eine Funktion mit R aufzuladen, um ein alternatives Verhalten zu bieten. Es ist eigentlich sehr einfach mit dem S3-Dispatch-System. Ich empfehle this ressource, um mehr zu erfahren.

Ich gebe Ihnen die verkürzte Version: Wenn Sie ein Objekt der Klasse "Myclass" haben, können Sie eine Funktion f.myclass schreiben, um zu tun, was Sie wollen.

Dann definieren Sie die generische Funktion f:

f <- function(obj, ...) UseMethod("f", obj, ...) 

Wenn Sie f(obj) rufen, dass die Funktion UseMethod hängt von der Klasse von obj nennen.

Wenn obj von der Klasse "myclass" ist, wird f.myclass auf obj aufgerufen.

Wenn die Funktion bereits vorhanden neu definiert werden soll, sagen plot, dann können Sie einfach plot.myclass definieren, welche verwendet wird, wenn Sie plot auf einem „myclass“ Objekt aufrufen. Die generische Funktion existiert bereits und muss nicht neu definiert werden.

Um die Klasse eines Objekts zu ändern (oder die neue Klasse an die vorhandenen Klassen anzuhängen, bei der das Verhalten, das nicht geändert werden soll, nicht unterbrochen wird), können Sie class<- verwenden.

Hier ist ein dummes Beispiel.

> print.myclass <- function(x) { 
    print("Hello!")} 

> df <- data.frame(a=1:3) 
> class(df) 
[1] "data.frame" 
> df #equivalent to print(df) 
    a 
1 1 
2 2 
3 3 

> class(df) <- append(class(df), "myclass") 
> class(df) 
[1] "data.frame" "myclass" 

> class(df) <- "myclass" 
> class(df) 
[1] "myclass" 
> df 
[1] "Hello!" 
> str(df) # checking the structure of df: the data is still there of course 
List of 1 
$ a: int [1:3] 1 2 3 
- attr(*, "row.names")= int [1:3] 1 2 3 
- attr(*, "class")= chr "myclass" 

Es gibt einige Feinheiten, wie, welche Funktion aufgerufen wird, wenn es mehrere Klassen sind, in welcher Reihenfolge etc. verweise ich Sie auf eine ausführliche Erläuterung des Systems S3.

So würden Sie das Verhalten von Funktionen neu definieren. Schreiben Sie sie erneut als f.myclass und erstellen Sie dann Objekte der Klasse "Myclass".

Alternativ könnten Sie f.targetclass neu definieren.Zum Beispiel wieder mit print und data.frame:

> print.data.frame <- function(x) { 
     print(paste("data.frame with columns:", paste(names(x), collapse = ", ")))} # less silly example! 
> df <- data.frame(a=1:3, b=4:6) 
> df 
[1] "data.frame with columns: a, b" 
Verwandte Themen