2014-08-29 10 views
12

In Perl (e probabilmente in altri linguaggi), è possibile "legare" una variabile per sostituire il suo comportamento predefinito con un comportamento definito dall'utente. Ad esempio, una tabella hash può essere associata a subroutine personalizzate "get" e "fetch" che, ad esempio, interrogano BerkeleyDB in modo che i dati siano persistenti e non limitati dalla RAM, ma continui a sembrare e agisca come un normale hash in Perl.Puoi "legare" o fornire un'implementazione alternativa di un data.frame in R?

È qualcosa di simile possibile con R? In particolare, stavo pensando, dal momento che un data.frame assomiglia molto a un tavolo in un db relazionale, che se un data.frame erano legati a qualcosa di simile SQLite, permetterebbe R per gestire grandi frame di dati (ho infilato 100GB + in SQLite) senza modifiche al codice.

+2

Prova pacchetto 'sqldf' per il vostro problema reale, ma penso che quello che lei propone è il meccanismo di classe S3. – James

+1

controlla i pacchetti 'ff' e' ffbase', sono costruiti esattamente su questo principio. –

+4

'data.table' e anche' dplyr' nuovo 'tbl_ *' – hrbrmstr

risposta

2

come i commenti sottolineano, una manciata di pacchetto è già stato costruito su questa idea (o simile).

data.table e dplyr sono eccezionalmente bravo a trattare con molto grande data.frame e l'esecuzione di query. Se data.frame è in realtà> 100 GB, preferirei preferire data.table che sembrano sovraperformare dplyr nel limite nrow-> Inf. Entrambi hanno un eccellente supporto su StackOverflow se ne hai bisogno.

Tuttavia, per rispondere alla tua domanda in realtà (e per essere utile ai futuri lettori di questo domanda): sì è possibile a pagamento di una funzione con R per fornire un comportamento alternativo. In realtà è molto semplice con il sistema di invio S3. Raccomando this ressource per saperne di più.

Ti darò la versione condensata: Se hai un oggetto di classe "myclass", puoi scrivere una funzione f.myclass per fare ciò che vuoi.

Poi si definisce la funzione generica f:

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

Quando si chiama f(obj), la funzione che UseMethod chiamerà dipende dalla classe di obj.

Se obj è di classe "MyClass", quindi f.myclass saranno chiamati a obj.

Se la funzione che si desidera ridefinire esiste già, dicono plot, allora si può semplicemente definire plot.myclass che verrà utilizzato quando si chiama plot su un oggetto "MyClass". La funzione generica esiste già, non è necessario ridefinirla.

Per modificare la classe di un oggetto (o aggiungere la nuova classe alle classi esistenti, che è più comune non interrompere il comportamento che non si desidera modificare), è possibile utilizzare class<-.

Ecco un esempio stupido.

> 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" 

ci sono alcune sottigliezze, come che la funzione viene chiamata se ci sono diverse classi, in quale ordine, ecc vi rimando ad una spiegazione approfondita del sistema S3.

Ecco come si ridefinire il comportamento delle funzioni. Re-scriverli come f.myclass e quindi creare oggetti di classe "myclass".

alternativa, è possibile ridefinire f.targetclass.Ad esempio, di nuovo con print e 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" 
Problemi correlati