• Publicidad

Comparar dos listas sin que cambie la posición

Perl aplicado a la bioinformática

Comparar dos listas sin que cambie la posición

Notapor alemanmd » 2012-02-02 16:56 @747

Hola a todos.

En esta ocasión busco ayuda por el siguiente inconveniente: tengo un código que me compara dos listas (son códigos ID). Si el ID de la lista 1 existe en la segunda columna de la lista 2, entonces imprime el ID correspondiente de la lista 1 y el ID correspondiente de la primera columna de la lista 2.

Bien, el programa hace eso, pero cuando reviso el archivo de salida me doy cuenta de que las posiciones cambian, es decir, el que era el código primero ya no lo es.

Para los fines que requiero es importante que haga la comparación pero que imprima sin alterar el orden de la lista 1.

¿Cómo puedo programar esto? ¿¿Hay algún comando que pueda utilizar??

Gracias de nuevo.

Cualquier comentario seguro será de gran ayuda, como siempre.

Enseguida les dejo mi código y les adjunto los archivos de entrada y cómo debería ser mi archivo de salida.
Saludos.


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/local/bin/perl
  2.  
  3. # Este programa compara un id de una lista con el de una segunda lista, si el ID es igual entonces imprime las variables que tu desees
  4. # funciona para  dos listas y los archivos se pueden usar sin importar el lugar (1.txt vs 2.txt o bien 2.txt vs 1.txt)
  5.  
  6. # uso:
  7. # perl extract_filas_lista.pl file1 file2
  8. # output: lista.txt
  9.  
  10. use strict;
  11.  
  12. my $file1 = $ARGV[0];                  # ingresa un archivo que se llamara file1
  13. my $file2 = $ARGV[1];                  # ingresa un archivo que se llamara file2
  14.  
  15. my %filas;
  16. my $n = 0;
  17. my $numero1;
  18.  
  19. open( LISTA, "$file1" ) || die("No puedo abrir $file1\n");
  20. while ( my $linea = <LISTA> ) {
  21.     chomp($linea);
  22.     if ( $linea =~ /(\d+)/ ) {         # este patrón se puede cambiar para adaptarse a tus necesidades
  23.         $numero1 = $1;
  24.         $filas{$numero1} = 0;
  25.         $n++;
  26.  
  27.         #print ("$numero1\n");
  28.     }
  29. }
  30. close(LISTA);
  31.  
  32. open( LISTA, "$file2" )       || die("No puedo abrir $file2\n");
  33. open( RES,   ">iguales.txt" ) || die("no puedo abrir secuencias.fasta\n");
  34. my %filas2;
  35.  
  36. my $n1 = 0;
  37. my $numero1;
  38. my $var1;
  39. my $var2;
  40. my @a;
  41. while ( my $linea = <LISTA> ) {
  42.     chomp($linea);
  43.     if ( $linea =~ /(\d+)/ ) {         # este patrón se puede cambiar para adaptarse a tus necesidades
  44.         my @a = split( /\t/, $linea );
  45.         $var1          = $a[0];
  46.         $var2          = $a[1];
  47.         $filas2{$var1} = $linea;
  48.         $n1++;
  49.  
  50.         #print ("$var1\n");
  51.         #print ("$var2\n");
  52.         if ( exists $filas{ $a[1] } ) {
  53.             print RES "$a[1]\t$var1\n";
  54.         }
  55.     }
  56. }
  57. close(LISTA);
  58. close(RES);
  59.  
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4




Mi archivo de salida debería ser así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
358395159          87581
358397962          45489
358397435          283182
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Adjuntos
2.txt
este es el archivo de la lista 2
(2.15 KiB) 98 veces
1.txt
Este es el archivo de la lista 1
(418 Bytes) 107 veces
Última edición por explorer el 2012-02-02 17:15 @760, editado 2 veces en total
Razón: Formateado de código con Perltidy y poner marcas Texto
alemanmd
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2011-11-28 20:16 @886

Publicidad

Re: Comparar dos listas sin que cambie la posición

Notapor explorer » 2012-02-02 17:11 @758

El problema está en el uso de hash para llevar el control de los elementos aparecidos. Sí que es correcto usarlo para saber de la existencia de los ID de una lista, pero el problema está en que el orden en que Perl almacena los valores dentro del hash, es algo completamente aleatorio, y diferente del orden en que se insertaron o crearon.

Una solución sería obligar a que el hash sí que almacene los valores en el mismo orden en que se insertan. Para ello, se puede usar el módulo Tie::IxHash.

Sería algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use Tie::IxHash;
  2. tie my %filas, Tie::IxHash;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Más información perldoc -q sorted.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Comparar dos listas sin que cambie la posición

Notapor alemanmd » 2012-02-03 15:06 @671

Hola explorer, ya inserté las lineas de código y descargué el paquete necesario. El programa corre pero aún sigue alterando el orden de las líneas durante la comparación. Revisé si en el hash %filas se almacenaba la información en el orden requerido y de hecho sí lo hace. Agregué la misma línea pero para el hash %filas2 del segundo archivo, pero sigo sin lograr hacer la comparación sin alterar el orden del archivo 1.

Saludos.
alemanmd
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2011-11-28 20:16 @886

Re: Comparar dos listas sin que cambie la posición

Notapor explorer » 2012-02-03 20:51 @911

Quien marca el orden de salida es el fichero 2. Observa que estás leyendo el fichero 2, línea a línea, y cuando hay coincidencia, imprime inmediatamente los datos del fichero 1. Por eso salen desordenados los datos del fichero 1: están saliendo según el orden de los datos del fichero 2.

La solución sería (una de varias) guardar los datos a imprimir en un %hash, que tenga como clave el valor de la clave de %filas, y el valor, la línea a imprimir. Luego, cuando hayas terminado con el bucle de las líneas del fichero 2, haces un nuevo bucle que recorra las claves de %filas (que sabemos que están en orden). Dentro del bucle, haces un if() parecido al de la línea 52, en donde compruebas la existencia del elemento $hash{$clave_del_1}. Si existe, entonces imprimes ese valor. Así, saldrá ordenado.

Una forma corta de resolver este problema es usando el operador 'coincidencia inteligente', de Perl v5.10: '~~'. No necesitarías tantos hash, aunque el programa podría volverse lento (si los ficheros tuvieran decenas de miles de líneas, claro).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Comparar dos listas sin que cambie la posición

Notapor explorer » 2012-02-03 20:58 @915

:oops: creo que la solución obvia (y sencilla) sería hacer el proceso inverso: leer primero el fichero 2 a memoria, y luego hacer el bucle por líneas con el fichero 1, que es el que marca el orden de salida.

A veces, lo mejor es parar y volver a plantearte el problema desde cero 8)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Bioinformática

¿Quién está conectado?

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