2012-06-26 27 views
18

R ha una semantica pass-by-value, che riduce al minimo gli effetti collaterali accidentali (una buona cosa). Tuttavia, quando il codice è organizzato in molte funzioni/metodi per la riusabilità/leggibilità/manutenibilità e quando quel codice ha bisogno di manipolare grandi strutture di dati attraverso, ad esempio, grandi frame di dati, attraverso una serie di trasformazioni/operazioni, la semantica pass-by-value conduce a un sacco di copia di dati in giro e molto heap thrashing (una cosa negativa). Ad esempio, un frame di dati che richiede 50 Mb sull'heap che viene passato come parametro di funzione verrà copiato almeno lo stesso numero di volte della profondità della chiamata della funzione e la dimensione dell'heap nella parte inferiore dello stack di chiamate sarà N * 50Mb. Se le funzioni restituiscono un frame di dati trasformato/modificato dal deep nella catena di chiamate, la copia sale di un altro N.R: il passaggio di un frame di dati per riferimento

La domanda SO What is the best way to avoid passing a data frame around? tocca questo argomento ma è formulata in modo tale da evitare di chiedere direttamente il pass-by - domanda di riferimento e la risposta vincente in pratica dice "sì, il valore per il passaggio è come funziona R". Questo in realtà non è accurato al 100%. Gli ambienti R consentono la semantica pass-by-reference e framework OO come proto utilizzano questa funzionalità in modo estensivo. Ad esempio, quando un oggetto proto viene passato come argomento di funzione, mentre il suo "wrapper magico" viene passato per valore, allo sviluppatore R la semantica è pass-by-reference.

Sembra che passare un grande data frame per riferimento sarebbe un problema comune e mi chiedo come gli altri si siano avvicinati e se ci siano librerie che lo abilitino. Nella mia ricerca non ne ho scoperto uno.

Se non è disponibile, il mio approccio sarebbe quello di creare un oggetto proto che avvolge un frame di dati. Apprezzerei i puntatori sullo zucchero sintattico che dovrebbe essere aggiunto a questo oggetto per renderlo utile, ad es. Sovraccaricare gli operatori $ e [[, nonché tutti i trucchi che dovrei cercare. Non sono un esperto di R.

Punti bonus per una soluzione di riferimento pass-agnostica che si integra perfettamente con R, sebbene le mie esigenze siano esclusivamente con frame di dati.

+4

Non credo che la premessa nella tua domanda sia corretta. R copia solo le modifiche, quindi puoi tranquillamente passare i commenti sullo stack delle chiamate senza fare nuove copie, purché non cambi l'oggetto.Proverò a trovarti qualche riferimento su questo in un minuto. – Andrie

+0

Vedere ad esempio questa domanda e la sua risposta da @matthewdowle: http://stackoverflow.com/q/10225098/602276 – Andrie

+2

Andrie ha ragione. Sorpreso che non hai trovato ['data.table'] (http://datatable.r-forge.r-project.org/LondonR_2012.pdf) nelle tue ricerche per' data.frame' di grandi dimensioni. Cosa hai cercato? –

risposta

26

La premessa della domanda è (parzialmente) errata. R funziona come pass-by-promise e viene ripetuta la copia nel modo in cui si delinea solo quando vengono assegnati ulteriori incarichi e modifiche al dataframe man mano che la promessa viene trasmessa. Quindi il numero di copie non sarà N * size dove N è la profondità dello stack, ma piuttosto dove N è il numero di livelli in cui vengono effettuati gli incarichi. Hai ragione, tuttavia, che gli ambienti possono essere utili. Vedo seguendo il link che hai già trovato il pacchetto 'proto'. C'è anche un'introduzione relativamente recente di una "classe di riferimento" a volte chiamata "R5" dove R/S3 era il sistema di classe originale di S3 che è copiato in R e R4 sarebbe il più recente sistema di classe che sembra supportare principalmente lo sviluppo del pacchetto BioConductor.

Ecco un link ad un esempio da Steve Lianoglou (in un thread discutere i meriti di classi di riferimento) di annegare un ambiente all'interno di un oggetto S4 per evitare le spese di copia:

https://stat.ethz.ch/pipermail/r-help/2011-September/289987.html

Matteo Dowle di Il pacchetto 'data.table' crea una nuova classe di oggetti di dati la cui semantica di accesso che utilizza "[" è diversa da quella dei normali dati di R.frames e che funziona davvero come un riferimento pass-by. Ha una velocità di accesso e elaborazione superiore. Può anche ricorrere alla semantica dei dataframe poiché negli anni successivi tali oggetti ora ereditano la classe "data.frame".

Si potrebbe anche voler indagare su Hesterberg's dataframe package.

+1

+1 Sono felice per te di espandere e migliorare questa risposta. – Andrie

+1

E +1 per il collegamento al pacchetto dataframe, che ora è incorporato (o almeno in filosofia) a R 2.15-1 – Andrie

+1

@DWin, grazie per le informazioni. Pass-by-promise ha senso come ottimizzazione, anche se non aiuta il mio caso in cui più passaggi operano sullo stesso frame dati per trasformarlo da "grezzo" a elaborabile. Di solito le modifiche vengono eseguite in fasi separate di una pipeline di elaborazione, ma in alcuni casi vengono eseguite nella stessa catena di chiamate, mentre i confini di astrazione con invarianti diversi vengono incrociati. Esaminerò i pacchetti che consigli. – Sim

Problemi correlati