Data era una delle caratteristiche ho esaminato prima che impegnato nell'apprendimento R. Per meglio o peggio, qui ci sono le mie osservazioni e soluzioni/palliativi su questi temi:
1. che R non gestisce i dati di grandi (> 2 GB?) Per me questo è un termine improprio. Per impostazione predefinita, le funzioni di input dei dati comuni caricano i dati nella RAM. Non per essere disinvolto, ma per me, questa è una caratteristica non un bug - ogni volta che i miei dati si adatteranno alla mia RAM disponibile, è lì che lo voglio. Allo stesso modo, una delle funzionalità più popolari di SQLite è l'opzione in memoria: l'utente ha la semplice possibilità di caricare l'intero dB nella RAM. Se i tuoi dati non si adattano alla memoria, allora R lo rende sorprendentemente facile da persistere, tramite connessioni ai comuni sistemi RDBMS (RODBC, RSQLite, RMySQL, ecc.), Tramite opzioni senza fronzoli come il pacchetto filehash e via sistemi che utilizzano le attuali tecnologie/pratiche (ad esempio, posso consigliare ff). In altre parole, gli sviluppatori R hanno scelto un valore ragionevole (e probabilmente ottimale) predefinito, dal quale è molto facile rinunciare.
2. Le prestazioni di read.table (read.csv, read.delim, et al.), I mezzi più comuni per ottenere dati in R, possono essere migliorate 5 volte (e spesso molto di più nella mia esperienza) semplicemente disattivando alcuni degli argomenti predefiniti di read.table - quelli che hanno il maggior effetto sulle prestazioni sono menzionati nella Guida di R (? read.table). In breve, gli sviluppatori R ci dicono che se fornisci valori per i parametri 'colClasses', 'nrows', 'sep' e 'comment.char' (in particolare, passa in '' se sai che il tuo file inizia con intestazioni o dati sulla linea 1), vedrai un significativo aumento delle prestazioni. Ho trovato che sia vero.
Qui ci sono i frammenti che uso per quei parametri:
Per ottenere il numero di righe nel file di dati (forniscono questo frammento come argomento per il parametro, 'nrows', nella chiamata a read.table):
as.numeric((gsub("[^0-9]+", "", system(paste("wc -l ", file_name, sep=""), intern=T))))
per ottenere le classi per ogni colonna:
function(fname){sapply(read.table(fname, header=T, nrows=5), class)}
Nota: non è possibile passare questo frammento come argomento, si deve chiamare per primo, poi passare il valore macerare urna - in altre parole, chiamare la funzione, associare il valore restituito a una variabile e quindi passare la variabile come valore al parametro 'colClasses' nella chiamata a read.table:
3. Utilizzo di Scan. Con un po 'più di fastidio, puoi fare di meglio (ottimizzando' read.table ') usando' scan 'invece di' read.table '(' read.table 'è in realtà solo un wrapper di' scan '). Ancora una volta, è molto facile da fare. Io uso 'scan' per inserire ogni colonna individualmente e poi costruisco il mio data.frame all'interno di R, cioè df = data.frame (cbind (col1, col2, ....)).
4. Utilizzare i contenitori R per la persistenza al posto dei formati di file ordinari (ad es., 'Txt', 'csv'). File di dati nativi di R '.RData 'è un formato binario un po' più piccolo di un file di dati txt compresso ('.gz'). Li crei usando risparmi (,). Si carica nuovamente nello spazio dei nomi R con carico(). La differenza nei tempi di caricamento rispetto a "read.table" è drammatica. Per esempio, w/a 25 file di MB (dimensioni non compresse)
system.time(read.table("tdata01.txt.gz", sep=","))
=> user system elapsed
6.173 0.245 **6.450**
system.time(load("tdata01.RData"))
=> user system elapsed
0.912 0.006 **0.912**
5. Prestare attenzione ai tipi di dati spesso può dare un incremento delle prestazioni e ridurre l'occupazione di memoria. Questo punto è probabilmente più utile nell'ottenere dati da R. Il punto chiave da tenere presente qui è che, per impostazione predefinita, i numeri nelle espressioni R vengono interpretati come virgola mobile a precisione doppia, ad esempio,> typeof (5) restituisce "double". " Confronta la dimensione dell'oggetto di una matrice di dimensioni ragionevoli di ciascuna e puoi vedere il significato (usa object.size()). Quindi costringi a numero intero quando puoi.
Infine, la famiglia di funzioni "apply" (tra le altre) non sono "loop nascosti" o loop wrapper. Sono loop implementati in C - grande differenza in termini di prestazioni. [edit: AWB ha correttamente sottolineato che mentre 'sapply', 'tapply' e 'mapply' sono implementati in C, 'apply' è semplicemente una funzione wrapper.
Per informazioni più recenti sulle prestazioni R, l'Advanced R di Hadley Wickham ha una sezione informativa su [performance] (http://adv-r.had.co.nz/Performance.html) e Jeffrey Horner ha scritto un paio di fantastici post su [Hash Table Performance in R] (http://jeffreyhorner.tumblr.com/post/114524915928/hash-table-performance-in-r-part-i). – cbare