• Publicidad

Datos repetidos

Perl aplicado a la bioinformática

Datos repetidos

Notapor asegurac » 2010-09-16 15:23 @683

Hola, nuevamente recurro a ustedes en busca de ayuda.

Estoy haciendo una manipulación de archivos de texto. Por ejemplo el primer archivo tiene la siguiente estructura (fragmento):
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  A        B     Score
HP0799  HP0172  0.698
HP0799  HP0172  0.698
HP0172  HP0799  0.698
HP0355  HP1195  0.581
HP1132  HP1420  0.675
HP1420  HP1132  0.675
HP1195  HP0355  0.581
HP0952  HP0329  0.651
HP0329  HP0952  0.651
HP0001  HP0002  0.483
HP0001  HP0002  0.695
HP0002  HP1574  0.641
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


El segundo archivo es una lista con la siguiente estructura (fragmento):
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
HP0799
HP0952
HP1132
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Con la lista del segundo archivo hago una búsqueda sobre el primer archivo para obtener los pares A-B donde están presentes cada uno de los elementos de lista. El resultado esperado debería ser algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
HP0799  HP0172  0.698
HP0799  HP0172  0.698
HP0172  HP0799  0.698
HP0952  HP0329  0.651
HP0329  HP0952  0.651
HP1132  HP1420  0.675
HP1420  HP1132  0.675
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Para ello, he escrito el siguiente código y aparentemente funciona:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #! /usr/bin/perl -w
  2.  
  3. my $file = $ARGV[0] || die "¡Error!\n\nNo encontre el archivo de la base de datos!\n";
  4.  
  5. my $list= $ARGV[1] || die "¡Error!\n\nNo encontre el archivo con los identificadores de las seed proteins!\n";
  6.  
  7. open (FILE,$file);
  8. open (LIST,$list);
  9.  
  10. my @array = <FILE>;
  11. my @alist =<LIST>;
  12.  
  13. for ($i=0;$i<scalar(@array);$i++){
  14.         chomp $array[$i];
  15.         my @cols=split(/\t/, $array[$i]);
  16.                        
  17.         foreach $j (@alist){
  18.         chomp $j;
  19.        
  20.  
  21.                 if (($j=~$cols[0])||($j=~$cols[1])){
  22.                        
  23.                         if ($cols[2]>=0.6){
  24.                                
  25.                                
  26.                         print "$cols[0]\t$cols[1]\t$cols[2]\n";
  27.                                
  28.                                 }              
  29.                         }
  30.                
  31.  
  32.         }
  33.                
  34.        
  35. }
  36. close FILE;
  37. close LIST;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Regresando al ejemplo anterior del resultado:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
HP0799  HP0172  0.698
HP0799  HP0172  0.698
HP0172  HP0799  0.698
HP0952  HP0329  0.651
HP0329  HP0952  0.651
HP1132  HP1420  0.675
HP1420  HP1132  0.675
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Observando los resultados vemos que hay información repetida. Por ejemplo: los dos primeros pares son el mismo y también el par HP0799-HP0172 es equivalente al par HP0172-HP0799.

Ya he intentado hacer algunas modificaciones a mi código para eliminar esta información repetida y no he tenido éxito. Alguien podría hacer alguna sugerencia para mi problema. Aclaración: la información ya viene repetida desde su origen y no es debido a la manipulación que hago de los archivos.

¡Gracias!

Saludos
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Publicidad

Re: Datos repetidos

Notapor explorer » 2010-09-16 19:11 @841

Yo veo que el resultado esperado es igual al resultado que muestras al final... entonces... ¡Funciona!

O... ¿es que lo que muestras como resultado esperado, está mal?

Recuerda que puedes editar tus propios mensajes, pulsando sobre el botón Editar mensaje, en el propio mensaje.
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: Datos repetidos

Notapor asegurac » 2010-09-16 22:37 @984

Hola,

Gracias por tu respuesta. Sin embargo, creo que en un afán de ser muy explicito terminé confundiendo.

En términos simples, el código que mostré en el mensaje anterior cumple con su trabajo y produce el siguiente resultado:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
HP0799  HP0172  0.698
HP0799  HP0172  0.698
HP0172  HP0799  0.698
HP0952  HP0329  0.651
HP0329  HP0952  0.651
HP1132  HP1420  0.675
HP1420  HP1132  0.675
HP1132  HP1111  0.875
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Es decir, obtengo los pares donde aparecen los elementos de mi lista.

El problema es que los datos de origen vienen duplicados. Así, tenemos que los dos primeros pares son el mismo (HP0799 HP0172) y el tercer par (HP0172 HP0799) sería equivalente a los dos primeros.

Mi solicitud de ayuda es la siguiente: ¿cuáles serían las modificaciones que podría hacer a mi código para eliminar la información redundante? Con tales modificaciones debería esperar un resultado como el siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
HP0799  HP0172  0.698
HP0952  HP0329  0.651
HP1132  HP1420  0.675
HP1132  HP1111  0.875
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Es decir, se eliminarían los pares repetidos, esto es lo que no he logrado hacer. Espero no haber vuelto a confundir. ¡Gracias!

Saludos
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Re: Datos repetidos

Notapor explorer » 2010-09-17 03:08 @172

Queda claro... eliminar las duplicidades. Eso es un trabajo para los hash, por ejemplo.

Se podría hacer lo siguiente: a medida de que vas leyendo el primer fichero, vas guardando la información en un hash, cuyas claves las formas con las dos columnas A y B, pero ordenadas con sort(). Y como valor, el del número de la tercera columna.

Luego, recorres el segundo fichero. Para cada fila del fichero, recorres todas las claves del hash. Le haces una exp. reg. que compruebe si la clave contiene el valor que hemos leído del segundo fichero. Si es así, imprimimos el valor de la clave y valor del hash (deshaciendo la clave en los dos valores anteriores).

Y ya está.

Ahora bien... ¿son muchas líneas?

P.D. Otra forma de hacerlo es guardando las líneas que hemos sacado al exterior en un hash, y antes de sacar la siguiente, comprobamos si no la hemos sacado ya.
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: Datos repetidos

Notapor asegurac » 2010-09-17 10:11 @466

Hola,

Muchas gracias por tu sugerencia, he realizado lo del hash y al parecer funciona! Tu pregunta acercade las lineas, son un poco mas de 9000, pero lo hace bastante rapido.

Saludos!
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Re: Datos repetidos

Notapor asegurac » 2010-09-17 11:44 @530

Hola de nuevo,

He analizado con más detalle la salida producida por mi código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #! /usr/bin/perl -w
  2.  
  3. my $file = $ARGV[0] || die "¡Error!\n\nNo encontré el archivo de la base de datos!\n";
  4.  
  5. my $list= $ARGV[1] || die "¡Error!\n\nNo encontré el archivo con los identificadores de las seed proteins!\n";
  6.  
  7. open (FILE,$file);
  8. open (LIST,$list);
  9.  
  10. my @array = <FILE>;
  11. my @alist =<LIST>;
  12. my %hash;
  13.  
  14. for ($i=0;$i<scalar(@array);$i++){
  15.         chomp $array[$i];
  16.         my @cols=split(/\t/, $array[$i]);
  17.         if ($cols[2]>=0.6){
  18.                        
  19.         $hash{$cols[0]}{$cols[1]}=$cols[2];
  20.         }
  21. }
  22.  
  23.  
  24.         for $j (@alist){
  25.         chomp $j;
  26.  
  27.                 for $k (sort keys %{ $hash{$j}}){
  28.  
  29.                 print "$j\t$k\t$hash{$j}{$k}\n";
  30.                 }
  31.         }
  32. close FILE;
  33. close LIST;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Con la lista que mostré anteriormente, funciona. Al modificar la lista de la siguiente manera:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
HP0799
HP0952
HP1132
HP0172
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Y utilizarla para hacer la búsqueda con el código modificado el resultado que produce es el siguiente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
HP0799  HP0172  0.698
HP0952  HP0329  0.651
HP1132  HP1111  0.875
HP1132  HP1420  0.675
HP0172  HP0799  0.698
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


El código eliminó los pares repetidos al tomar como llave a los pares. En el caso del último par, que sería equivalente al primero, no lo filtra, supongo que dado que ahora los elementos están invertidos, el hash los toma como una llave diferente y por eso los sigue imprimiendo. ¿Cómo podría corregir esto?

Saludos
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Re: Datos repetidos

Notapor explorer » 2010-09-17 14:17 @636

Lo que pasa es que estás creando un hash de dos dimensiones, es decir, un hash que contiene una referencia a otros hash. Para cada valor leído del segundo fichero, deberías no solo buscarlo en la primera dimensión, sino también en la segunda (para lo cuál, deberías volver a recorrer la primera dimensión: buscar todas las claves correspondientes a cada clave de la primera).

La solución que te comenté es la de combinar las dos nombres para que juntos formen una sola clave. Y ordenados, para evitar las duplicidades por estar intercambiados los nombres, en cada fila.

Esta es una versión que implanta esa solución:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use strict;
  4. use warnings;
  5. use diagnostics;
  6.  
  7. use Data::Dumper;
  8.  
  9.  
  10. ### Comprobamos los argumentos pasados al programa
  11. @ARGV == 2  or  die "Uso: $0 <fichero 1> <fichero 2>\n";
  12.  
  13. my ($fichero1, $fichero2) = @ARGV;
  14.  
  15.  
  16. ### Leer la información del primer fichero
  17. my %scores;
  18.  
  19. open my $FILE1, q[<], $fichero1  or  die "ERROR: No puedo leer el fichero $fichero1: $!\n";
  20. while (<$FILE1>) {
  21.     chomp;
  22.     my @columnas = split;
  23.     next if @columnas != 3;
  24.  
  25.     $scores{ join q[;], sort @columnas[0,1] } = $columnas[2];
  26. }
  27. close   $FILE1;
  28.  
  29. say Dumper \%scores;
  30.  
  31.  
  32. ### Leer la lista del segundo fichero
  33. open my $FILE2, q[<], $fichero2  or  die "ERROR: No puedo leer el fichero $fichero2: $!\n";
  34. chomp(my @claves = <$FILE2>);
  35. close $FILE2;
  36.  
  37. my $claves = join q[|], @claves;
  38. $claves = qr($claves);
  39.  
  40. say Dumper $claves;
  41.  
  42.  
  43. ### Presentar la lista de claves solicitadas
  44. for my $score (keys %scores) {
  45.     if ($score =~ $claves) {
  46.         say join "\t", split(/;/, $score), $scores{$score};
  47.     }
  48. }
  49.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
La salida es
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'HP0329;HP0952' => '0.651',
          'HP0002;HP1574' => '0.641',
          'HP0172;HP0799' => '0.698',
          'HP1132;HP1420' => '0.675',
          'HP0355;HP1195' => '0.581',
          'HP0001;HP0002' => '0.695',
          'A;B' => 'Score'
        };

$VAR1 = qr/(?-xism:HP0799|HP0952|HP1132|HP0172)/;

HP0329  HP0952  0.651
HP0172  HP0799  0.698
HP1132  HP1420  0.675
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

El funcionamiento es:
* de la línea 10 a 13, leemos los argumentos
* del 17 al 29 leemos el primer fichero. Metemos cada línea de puntuación en una clave/valor de un hash. La clave se forma uniendo las dos columnas ordenadas con sort(), con el carácter ';'
* del 33 al 40 leemos el segundo fichero. Cada nombre irá a parar a un array, que luego se transformará en una expresión regular (que es la que sale en pantalla), compuesta por todos los nombres unidos con '|', significando "alternativas" dentro de una exp. reg.
* del 44 al 48 hacemos la salida. Consiste en hacer un bucle por todas las claves leídas desde el fichero primero, ver si coinciden con la expresión regular construida a partir del segundo fichero, y en ese caso, hacemos una salida formateada con tabuladores. Observar que usamos split() para deshacer la unión de los nombres unidos por ';', para unirlos ahora con "\t", junto con el valor de la puntuación.

El truco está en la línea 25: combinamos los dos nombres en una sola clave. Y en la línea 45, la búsqueda que hace la exp. reg. que hemos construido unas líneas antes.

Ejemplo, en una de las vueltas del último bucle se realiza la siguiente comparación:

if ( 'HP0329;HP0952' =~ /HP0799|HP0952|HP1132|HP0172/ ) {

En este caso, la comparación resulta verdadera, porque la cadena "HP0952" sí que está en la cadena de prueba (la de la izquierda).
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 1 invitado