2012-03-26 19 views
11

Quiero transmitir una tabla de datos grandes en R LINE BY LINE, y si la línea actual tiene una condición específica (digamos que las primeras columnas son> 15), agregue la línea a un dato marco en la memoria. He escrito el código siguiente:R - Leer STDIN línea por línea

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); 

Pero me sale el error "datos no disponibles". Tenga en cuenta que mis datos son grandes y no quiero leerlos todos una vez y aplicar mi condición (en este caso fue fácil).

+0

Usted puede estar interesado en las respuestas y los comentarios de esta q:? Http://stackoverflow.com/questions/9352887/strategies-for-reading-in-csv-files-in-pieces –

+0

véase 'escanear ','? readLines', 'nrows' argumento de' read.table', y tenga en cuenta que su solución será ** muy ** lenta en R - ¿puede usar Perl, o incluso awk, para preprocesar? –

+1

¿Cómo le iría a mi respuesta a continuación en términos de velocidad? En esencia, abro un archivo y sigo extrayendo líneas de él sin cerrar el archivo. –

Respuesta

11

Creo que sería más sensato usar una función R como readLines. readLines admite solo la lectura de un número específico de líneas, p. 1. Combine eso con abrir primero una conexión file, y luego llamar al readLines repetidamente le consigue lo que desea. Al llamar varias veces al readLines, se leen las siguientes líneas n de la conexión. En el código 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) 
    } 
} 

Comentarios adicionales:

  • R tiene una forma interna de tratamiento de la entrada estándar como archivo: stdin(). Sugiero que use esto en lugar de usar pipe('cat /dev/stdin'). Esto probablemente lo hace más robusto, y definitivamente más multiplataforma.
  • Inicializas Mydata al principio y sigues creciendo usando rbind. Si el número de líneas que rbind aumenta, esto se volverá realmente lento. Esto tiene que ver con el hecho de que cuando el objeto crece, el sistema operativo necesita encontrar una nueva ubicación de memoria para él, lo que termina tomando mucho de tiempo. Mejor es preasignar MyData, o usar aplicar bucles de estilo.
+0

Gracias por la respuesta. Pero tengo una pregunta al respecto: como mencioné, mis datos son muy GRANDES y no quiero leerlos en la memoria. En la línea 3 de tu código, parece que estás leyendo toda la información y luego pasando por sus líneas. ¿Estoy en lo cierto? – user1250144

+0

No, abro una conexión y luego leo de ella. 'next_line' solo contiene solo la línea actual. Usar 'file' solo abre una conexión, todavía no lee nada. –

+0

Ahan. Gracias. ¿Qué debo escribir en lugar de "/tmp/test.txt", el primer argumento de file()? – user1250144

Cuestiones relacionadas