• Publicidad

Comparar dos archivos muy grandes

Perl aplicado a la bioinformática

Comparar dos archivos muy grandes

Notapor msohh » 2011-07-28 01:39 @110

Hola amigos, es mi primera pregunta, espero me puedan ayudar.
Tengo dos archivos; uno con 353990 líneas y otro con 1350274 líneas.
Deseo extraer las líneas idénticas e imprimirlas en otro archivo.
Tengo un código, pero demora demasiado, excesivamente mucho.
El código que tengo es el siguiente

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. use strict;
  4.  
  5. my $id_file1 = shift @ARGV;
  6. my $id_file2 = shift @ARGV;
  7.  
  8. system("grep -f $id_file1 $id_file2 > tmp_file2");
  9.  
  10. open IN, "tmp_file2";
  11.  
  12. while( my $line = <IN> )
  13. {
  14.   print $line;
  15. }
  16.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


y le paso los archivos por parámetros.

archivo 1
AT1G22070,AT1G06400
AT1G22070,AT1G10290
AT1G22070,AT1G12080
AT1G22070,AT1G18190


archivo 2
AT1G22070,AT1G06400
AT3G2070,AT7G329234
AT1G22070,AT1G12022
AT3G72070,AT1389445
AT1G22070,AT1G20090


Espero me puedan ayudar.
msohh
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2011-07-27 23:50 @035

Publicidad

Re: Comparar dos archivos muy grandes

Notapor explorer » 2011-07-28 06:53 @329

Bienvenido a los foros de Perl en español, msohh.

Lo de buscar coincidencias entre ficheros es algo normal por estos foros. Ya lo hemos comentado en otros hilos de este subforo de Bioinformática, como por ejemplo:

Si tienes memoria suficiente, puedes intentar hacer toda la operación 'in situ':
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use Modern::Perl;               # somos modernos
  3. #use utf8;                      # este programa está escrito en utf8
  4. use autodie;                    # es mejor morir que regresar con deshonor (proverbio Klingon)
  5. #use open qw(:utf8 :std);       # la salida y la entrada estándar serán en utf8
  6.  
  7. use File::Slurp;
  8. use Set::Scalar;
  9.  
  10. my $fichero_primero = Set::Scalar->new(read_file('perlspanish/source/perlfunc.pod'));
  11. my $fichero_segundo = Set::Scalar->new(read_file('perlspanish/target/perlfunc.pod'));
  12.  
  13. say $fichero_primero->intersection($fichero_segundo)->elements;
  14.  
  15. __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
pero... ¡ojo! Solo devuelve los valores comunes a los dos ficheros, y solo una vez.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Comparar dos archivos muy grandes

Notapor msohh » 2011-07-28 21:08 @922

Gracias por la pronta respuesta, pero demora mucho la búsqueda.
¿Al hacerlo con hash demorara menos?
¿Se puede hacer eso?

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
clave_______..................valores.................    
AT1G22070=> AT1G06400, AT1G10290, AT1G12080, AT1G18190
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


¿Conoce algún manual donde expliquen bien como usar hash?

Muchas gracias
msohh
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2011-07-27 23:50 @035

Re: Comparar dos archivos muy grandes

Notapor explorer » 2011-07-28 21:28 @936

¿Qué solución va lenta? ¿El código de ejemplo que te he puesto con Set::Scalar?

Internamente, el método intersection() usa hash. Lo que quizás notas que vaya lento es porque es una subrutina genérica para realizar operaciones lógicas entre conjuntos de valores, mientras que en tu problema solo deseas resolver un problema muy específico.

Sí, la solución sería usar hash, pero no de la clave, sino de toda la línea (es lo que nos pides en el primer mensaje: comparar líneas enteras).

Lo que puedes hacer es leer el primer fichero entero, metiendo cada línea en un hash. Luego abres el segundo archivo, leyendo línea a línea, y miras a ver si la línea que estás leyendo está o no en el hash. Si está, entonces hay una coincidencia, y la grabas al fichero de salida. En los hilos que te indico las soluciones son así, usando hash (o el operador de coincidencia inteligente ~~).

Tienes información sobre los hash en muchos sitios.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Comparar dos archivos muy grandes

Notapor msohh » 2011-07-28 22:41 @987

Primero que todo, excelente su página.
Muy buena la ayuda.

Perdón por mi ignorancia, pero tengo un problema al ejecutar el que me mando usted.
Modifiqué una parte de éste (nombre del archivo que deseo abrir) y me quedó así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use Modern::Perl;               # somos modernos
  3. #use utf8;                      # este programa está escrito en utf8
  4. use autodie;                    # es mejor morir que regresar con deshonor (proverbio Klingon)
  5. #use open qw(:utf8 :std);       # la salida y la entrada estándar serán en utf8
  6.  
  7. use File::Slurp;
  8. use Set::Scalar;
  9.  
  10. my $fichero_primero = Set::Scalar->new(read_file('file1'));
  11. my $fichero_segundo = Set::Scalar->new(read_file('file2'));
  12.  
  13. say $fichero_primero->intersection($fichero_segundo)->elements;
  14.  
  15. __END__
  16.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y cuando lo ejecuto con el comando ./m.pl me da el siguiente error

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
./m.pl: línea 3: use: orden no encontrada
./m.pl: línea 5: use: orden no encontrada
./m.pl: línea 8: use: orden no encontrada
./m.pl: línea 9: use: orden no encontrada
./m.pl: línea 11: error sintáctico cerca del elemento inesperado `('
./m.pl: línea 11: `my $fichero_primero = Set::Scalar->new(read_file('file1'));'
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Además, anexo los archivos que estoy utilizando.

Teóricamente los archivos se componen de líneas con 2 campos, separados por una coma. Existen varias líneas con igual campo 1 y diferente campo 2, es por eso que pensaba hacer algo con hash o algo similar a lista enlazada.

Saludos.

Este es el formato de los 2 archivos, pero, obviamente, mucho más largos.
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
AT4G15980,AT1G15360
AT4G15980,AT1G75490
AT4G15980,AT1G54330
AT4G15980,AT2G40210
AT4G15980,AT2G28610
AT4G15980,AT1G65360
AT4G15980,AT1G22810
AT4G15980,AT2G20880
AT4G15980,AT2G40740
AT4G15980,AT2G34820
AT4G15980,AT2G33880
AT4G15980,AT2G45650
AT4G16020,AT1G25330
AT4G16020,AT1G25340
AT4G16020,AT5G16770
AT4G16020,AT1G31640
AT4G16020,AT5G27050
AT4G16020,AT5G65070
AT4G16020,AT5G64060
AT4G16020,AT5G61890
AT4G16020,AT5G59340
AT4G16020,AT5G58890
AT4G16020,AT5G46350
AT4G16020,AT5G46010
AT4G16020,AT5G40360
AT4G16020,AT5G39700
AT4G16020,AT5G38800
AT4G16020,AT5G23000
AT4G16020,AT5G18560
AT4G16020,AT5G12870
AT4G16020,AT3G44350
AT4G16020,AT4G35900
AT4G16020,AT4G33970
AT4G16020,AT4G28140
AT4G16020,AT4G21050
AT4G16020,AT4G21080
AT4G16020,AT4G09960
AT4G16020,AT1G12630
AT4G16020,AT3G15170
AT4G16020,AT3G19020
AT4G16020,AT3G30210
AT4G16020,AT3G23240
AT4G16020,AT3G17010
AT4G16020,AT3G29020
AT4G16020,AT3G19500
AT4G16020,AT3G27785
AT4G16020,AT3G04410
AT4G16020,AT3G02940
AT4G16020,AT1G63910
AT4G16020,AT1G68320
AT4G16020,AT1G21340
AT4G16020,AT1G12260
AT4G16020,AT1G26790
AT4G16020,AT1G26780
AT4G16020,AT1G28360
AT4G16020,AT1G35515
AT4G16020,AT1G77980
AT4G16020,AT1G15360
AT4G16020,AT2G28610
AT4G16020,AT2G22200
AT4G16020,AT2G42830
AT4G16020,AT1G22810
AT4G16020,AT1G60280
AT4G16020,AT1G55600
AT4G16020,AT2G17770
AT4G16020,AT2G20880
AT4G16020,AT2G15660
AT4G16020,AT2G13150
AT4G16020,AT2G25820
AT4G16040,AT1G25330
AT4G16040,AT1G26310
AT4G16040,AT5G11050
AT4G16040,AT5G21120
AT4G16040,AT4G36590
AT4G16040,AT5G65590
AT4G16040,AT5G61890
AT4G16040,AT5G61620
AT4G16040,AT5G48670
AT4G16040,AT5G45980
AT4G16040,AT5G46010
AT4G16040,AT5G42910
AT4G16040,AT5G39700
AT4G16040,AT5G38800
AT4G16040,AT5G35550
AT4G16040,AT5G23650
AT4G16040,AT5G23260
AT4G16040,AT5G07310
AT4G16040,AT5G06500
AT4G16040,AT3G56660
AT4G16040,AT3G53790
AT4G16040,AT4G33970
AT4G16040,AT4G28140
AT4G16040,AT4G26930
AT4G16040,AT4G21050
AT4G16040,AT4G18770
AT4G16040,AT4G17980
AT4G16040,AT4G13480
AT4G16040,AT4G12350
AT4G16040,AT4G04450
AT4G16040,AT4G01500
AT4G16040,AT1G12630
AT4G16040,AT1G34170
AT4G16040,AT3G06120
AT4G16040,AT3G19020
AT4G16040,AT3G13540
AT4G16040,AT3G18650
AT4G16040,AT3G29020
AT4G16040,AT3G27785
AT4G16040,AT3G30530
AT4G16040,AT3G04410
AT4G16040,AT3G03260
AT4G16040,AT3G09370
AT4G16040,AT3G01530
AT4G16040,AT1G69560
AT4G16040,AT1G66370
AT4G16040,AT1G80590
AT4G16040,AT1G07540
AT4G16040,AT1G26790
AT4G16040,AT1G18750
AT4G16040,AT1G56160
AT4G16040,AT1G77980
AT4G16040,AT1G77950
AT4G16040,AT1G62700
AT4G16040,AT1G75490
AT4G16040,AT1G54330
AT4G16040,AT2G27220
AT4G16040,AT2G40200
AT4G16040,AT2G28700
AT4G16040,AT2G24840
AT4G16040,AT1G26870
AT4G16040,AT2G36450
AT4G16040,AT2G12900
AT4G16040,AT1G02250
AT4G16040,AT1G65360
AT4G16040,AT1G61110
AT4G16040,AT2G20880
AT4G16040,AT2G15660
AT4G16040,AT2G13150
AT4G16040,AT2G17950
AT4G16040,AT2G26960
AT4G16040,AT2G32370
AT4G16040,AT2G22750
AT4G16040,AT2G22760
AT4G16040,AT2G25820
AT4G16040,AT2G34440
AT4G16040,AT2G32460
AT4G16040,AT2G34820
AT4G16050,AT5G17320
AT4G16050,AT1G66380
AT4G16050,AT2G27220
AT4G16050,AT2G13150
AT4G16060,AT1G26150
AT4G16060,AT4G36870
AT4G16060,AT5G02030
AT4G16060,AT4G32980
AT4G16060,AT3G15270
AT4G16060,AT1G74430
AT4G16060,AT2G03710
AT4G16060,AT2G33810
AT4G16090,AT3G56660
AT4G16090,AT2G40220
AT4G16110,AT5G54230
AT4G16110,AT5G15130
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
msohh
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2011-07-27 23:50 @035

Re: Comparar dos archivos muy grandes

Notapor explorer » 2011-07-29 10:10 @465

Los mensajes de error

./m.pl: línea 3: use: orden no encontrada
./m.pl: línea 5: use: orden no encontrada
...


indican que su sistema no se ha dado cuenta de que se trata de un programa Perl.

Compruebe que la primera línea del programa es la que comienza por '#!...' (la línea shebang).

Si esa línea es correcta, quizás es que el intérprete de Perl no esté en /usr/bin/. Pr favor, ponga la ruta completa al intérprete perl

Otra forma de ejecutarlo es:

perl ./m.pl

Además, asegúrese de que tiene instalados los módulos que va a necesitar: Modern::Perl, autodie, File::Slurp y Set::Scalar. autodie es opcional y lo puede quitar. Modern::Perl solo lo usamos para el say(), así que lo puede quitar también y sustituir say() por un print(). File::Slurp lee un fichero, pero sabe que puede sustituir la función read_file() por la clásica terna open(FILE), <FILE>, close FILE. El único módulo que no puede sustituir de forma clara es Set::Scalar (bueno, es ahí donde está la magia).

P.D. Y hay que decidir si quiere comparar solo una clave o toda la línea. Si solo quiere comparar una clave, la solución ya está descrita en los otros hilos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Comparar dos archivos muy grandes

Notapor msohh » 2011-07-29 18:18 @804

Nuevamente por acá. Por fin logré sacar los errores, instalé los módulos, no los tenía, pero al ejecutar el programa, no hace nada. No me entrega ninguna salida ni nada.

¿Qué podrá ser?
msohh
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2011-07-27 23:50 @035

Re: Comparar dos archivos muy grandes

Notapor explorer » 2011-07-29 18:23 @808

Si no sale nada, la respuesta inmediata es que no hay líneas coincidentes.

Haz una prueba con un par de ficheros, más pequeños, e idénticos (uno que sea la copia del otro), y prueba el programa. Deberían salir todas las líneas.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Comparar dos archivos muy grandes

Notapor msohh » 2011-07-30 15:53 @704

EXPLORER, ERES MAESTRO.
Muchas gracias por tu ayuda, de verdad me sirvió mucho y ahorro tiempo, es increíble.

Otra pregunta, ¿existirá alguna manera de hacer lo mismo, pero usando la memoria del disco duro? Aunque sea más lento, porque es poca RAM, luego de un tiempo, se cae.

Bueno, muchas gracias nuevamente, eres muy buena persona.
msohh
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2011-07-27 23:50 @035

Re: Comparar dos archivos muy grandes

Notapor explorer » 2011-07-30 19:42 @862

¿Cómo que se cae?

¿Qué es lo que se cae? ¿El programa o el sistema operativo o el ordenador entero?

¿Qué sistema operativo estás usando?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Bioinformática

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 24 invitados

cron