2012-03-26 6 views
11

Voglio trasmettere una grande tabella di dati in R LINE BY LINE e se la riga corrente ha una condizione specifica (diciamo che le prime colonne sono> 15), aggiungi la linea a un dato cornice nella memoria. Ho scritto il seguente codice:R - Lettura STDIN riga per riga

count<-1; 
Mydata<-NULL; 
fin <- FALSE; 
while (!fin){ 
    if (count==1){ 
     Myrow=read.delim(pipe('cat /dev/stdin'), header=F,sep="\t",nrows=1); 
     Mydata<-rbind(Mydata,Myrow); 
     count<-count+1; 
    } 
    else { 
     count<-count+1; 
     Myrow=read.delim(pipe('cat /dev/stdin'), header=F,sep="\t",nrows=1); 
     if (Myrow!=""){ 
     if (MyCONDITION){ 
      Mydata<-rbind(Mydata,Myrow); 
     } 
     } 
     else 
     {fin<-TRUE} 
    } 
} 
print(Mydata); 

Ma ho ricevuto l'errore "dati non disponibili". Si prega di notare che i miei dati sono grandi e non voglio leggere tutto in una volta e applicare la mia condizione (in questo caso è stato facile).

+0

Potreste essere interessati alle risposte e commenti su questo q:? Http://stackoverflow.com/questions/9352887/strategies-for-reading-in-csv-files-in-pieces –

+0

vedere 'scansione ','? readLines', argomento 'nrows' di' read.table', e sii consapevole che la tua soluzione sarà ** very ** slow in R - puoi usare Perl, o anche awk, per pre-processare? –

+1

Come sarebbe la mia risposta in basso in termini di velocità? In sostanza apro un file e continuo a estrarre le righe da esso senza chiudere il file. –

risposta

11

Penso che sarebbe più saggio utilizzare una funzione R come readLines. readLines supporta solo la lettura di un numero specificato di righe, ad es. 1. Combina questo con l'apertura di una connessione file prima e poi chiamando readLines ripetutamente ti ottiene quello che vuoi. Quando si chiama readLines più volte, le successive linee n vengono lette dalla connessione. Nel Codice R:

stop = FALSE 
f = file("/tmp/test.txt", "r") 
while(!stop) { 
    next_line = readLines(f, n = 1) 
    ## Insert some if statement logic here 
    if(length(next_line) == 0) { 
    stop = TRUE 
    close(f) 
    } 
} 

Ulteriori commenti:

  • R ha un modo di trattare interna stdin come file di: stdin(). Ti suggerisco di usare questo invece di usare pipe('cat /dev/stdin'). Questo probabilmente lo rende più robusto e sicuramente più multipiattaforma.
  • Si inizializza Mydata all'inizio e si continua a crescere utilizzando rbind. Se il numero di linee che si aumenta di rbind diventa molto lento. Questo ha a che fare con il fatto che quando l'oggetto cresce, il sistema operativo deve trovare una nuova posizione di memoria per questo, che finisce per prendere molto tempo. È meglio pre-allocare MyData o utilizzare applicare i loop di stile.
+0

Grazie per la risposta. Ma ho delle domande a riguardo: come ho detto, i miei dati sono molto GRANDI e non voglio leggerli in memoria. Nella riga 3 del tuo codice, sembra che tu stia leggendo l'intero dato e poi attraversando le sue linee. Ho ragione? – user1250144

+0

No, apro una connessione e quindi leggo da essa. 'next_line' contiene solo la riga corrente. L'uso di 'file' apre solo una connessione, non legge ancora nulla. –

+0

Ahan. Grazie. cosa dovrei scrivere al posto di "/tmp/test.txt", il primo argomento di file()? – user1250144