• Publicidad

Leer registros de forma alterna

Perl aplicado a la bioinformática

Leer registros de forma alterna

Notapor anush » 2010-01-11 07:19 @347

Buenos días, llevo varios días con un problema y no sé cómo solucionarlo:

Tengo un archivo en formato FASTA de la siguiente manera:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
>NUMEROS
12345
67891

>LETRAS
ABCDE
FGHIJ

>NUMEROS
12345
67891

>LETRAS
ABCDE
FGHIJ
...
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Quiero quedarme solo con los números, pero no debo basarme en el hecho de que sean números o letras, sino que el primer formato fasta tiene números y el segundo letras, y esto se repite.

Gracias.
anush
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2009-12-30 13:15 @594

Publicidad

Re: Problema con un fichero

Notapor explorer » 2010-01-11 07:33 @356

Se puede hacer de muchas formas...

La primera que se me ocurre: Vamos leyendo línea a línea. Cada vez que encontramos una nueva sección ('>'), cambiamos una variable de estado. Si estaba a 0, la pasamos a 1. Y al revés. Así sabemos, para el resto de líneas, en qué sección estamos. Se podría llamar... $en_NUMEROS :)

Luego pongo otras formas, que se me ocurran.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Problema con un fichero

Notapor explorer » 2010-01-11 12:44 @572

Otra forma sería leer todo el fichero, dividirlo en registros, y separarlos según la posición que ocupan.

Algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. open my $fasta, q[<], 'fasta.txt' or die "$!\n";
  7. local $/ = undef;
  8. my $fichero = <$fasta>;
  9. close $fasta;
  10.  
  11. my @registros = grep { /./  } split "\s*>", $fichero;
  12. my @numeros;
  13. my @letras;
  14.  
  15. for (my $i = 0; $i < @registros; $i++) {
  16.  
  17.     if ($i % 2) {
  18.         push @letras, $registros[$i];
  19.     }
  20.     else {
  21.         push @numeros, $registros[$i];
  22.     }
  23. }
  24.  
  25. use Data::Dumper;
  26. print Dumper \@registros;
  27. print Dumper \@numeros;
  28. print Dumper \@letras;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Problema con un fichero

Notapor anush » 2010-01-11 13:04 @586

Gracias, ¿pero no hay una manera más sencilla?
anush
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2009-12-30 13:15 @594

Re: Problema con un fichero

Notapor explorer » 2010-01-11 14:50 @660

Creo que no... al final, en las dos soluciones, debes usar una condición para saber dónde dejar el registro.

Se puede "esconder" el procedimiento ocultando y compactando código, pero... no queda muy claro...

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. open my $fasta, q[<], 'fasta1.txt' or die "$!\n";
  7. local $/ = undef;
  8. my $fichero = <$fasta>;
  9. close $fasta;
  10. print "$fichero\n";
  11.  
  12. my @numeros;
  13. my @letras;
  14.  
  15. while ($fichero =~ />.*?$([^>]+)>.*?$([^>]+)/gsmo) {
  16.     my ($numeros,$letras) = ($1, $2); # Los dos registros capturados
  17.     $numeros =~ s/\s*//g;             # les quitamos los espacios y finales de línea
  18.     $letras  =~ s/\s*//g;
  19.     push @numeros, $numeros;          # lo guardamos
  20.     push @letras,  $letras;
  21. }
  22.  
  23. use Data::Dumper;
  24. print Dumper \@numeros;
  25. print Dumper \@letras;
  26.  
  27. __END__
  28. >NUMEROS
  29. 12345
  30. 67891
  31. >LETRAS
  32. ABCDE
  33. FGHIJ
  34. >NUMEROS
  35. 12345
  36. 67891
  37. >LETRAS
  38. ABCDE
  39. FGHIJ
  40.  
  41. $VAR1 = [
  42.           '1234567891',
  43.           '1234567891'
  44.         ];
  45. $VAR1 = [
  46.           'ABCDEFGHIJ',
  47.           'ABCDEFGHIJ'
  48.         ];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Esta solución usa una expresión regular para capturar dos registros contiguos.

Esta otra es aún más compacta, generando una estructura de datos de un array de array:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. open my $fasta, q[<], 'fasta1.txt' or die "$!\n";
  7. local $/ = undef;
  8. my $fichero = <$fasta>;
  9. close $fasta;
  10. print "$fichero\n";
  11.  
  12. my @registros;
  13.  
  14. my $i = 0;
  15. while ($fichero =~ />.*?$([^>]+)/gsmo) {
  16.     my $registro = $1;                     # lo capturado
  17.     $registro =~ s/\s*//g;                 # quitamos los espacios y finales de línea
  18.     push @{$registros[$i % 2]}, $registro; # lo guardamos según el valor de $i
  19.     $i++;                                  # contador
  20. }
  21.  
  22. use Data::Dumper;
  23. print Dumper \@registros;
  24.  
  25. __END__
  26. >NUMEROS
  27. 12345
  28. 67891
  29. >LETRAS
  30. ABCDE
  31. FGHIJ
  32. >NUMEROS
  33. 12345
  34. 67891
  35. >LETRAS
  36. ABCDE
  37. FGHIJ
  38.  
  39. $VAR1 = [
  40.           [
  41.             '1234567891',
  42.             '1234567891'
  43.           ],
  44.           [
  45.             'ABCDEFGHIJ',
  46.             'ABCDEFGHIJ'
  47.           ]
  48.         ];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Yo creo que quede más clara la opción primera, la de la variable que hace de indicador.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer registros de forma alterna

Notapor anush » 2010-01-12 10:10 @465

Lo he intentado de la siguiente manera:
Supongamos que fichero tiene esta forma

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. >numeros
  2. 12345
  3. 67891
  4. 78923
  5. >letras
  6. adfjsfdaf
  7. asfdgsdfg
  8. safaadfgd
  9. >numeros
  10. 12345
  11. 67891
  12. 78923
  13. >letras
  14. adfjsfdaf
  15. asfdgsdfg
  16. safaadfgd
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


He hecho esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $cuenta = 0;
  2. my(@numeros) = (  );
  3. my $posicion = 0;
  4. my $linea;
  5. foreach $linea (@fichero) {
  6.    if ($linea=~ /^>/) {   #Si empieza con >
  7.        ++$cuenta;          #suma uno a la cuenta
  8.           unless ($cuenta % 2 == 0) {  #Si no es divisible por 2
  9.                 do {                   #haz lo siguiente
  10.                     ++$posicion;
  11.                     push( @numeros,$fichero[$posicion]);
  12.                                      
  13.                     } until {$fichero[$posicion]=~ /^>/} #Hasta que empiece con >
  14.                  }
  15.       }
  16. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Pero no funciona, ¿que tengo mal?
anush
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2009-12-30 13:15 @594

Re: Leer registros de forma alterna

Notapor explorer » 2010-01-12 11:05 @503

Huy... no es nada aconsejable el mezclar varios índices de acceso dentro de un mismo array... puedes tener problemas...

Esta solución es muy básica, pero da la secuencia de números. Basada en tu solución.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. # Leemos el fichero que hay después de DATA
  7. my @fichero = <DATA>;
  8.  
  9. my $cuenta = 0;             # Número de registro
  10. my $numeros;                # La secuencia de números
  11. for my $linea (@fichero) {  # Para todas las líneas del @fichero
  12.     if ($linea =~ /^>/) {       # Si la $linea empieza con '>'
  13.         ++$cuenta;              # Tenemos un registro más
  14.         next;                   # Pasamos a la siguiente línea
  15.     }
  16.     unless ($cuenta % 2 == 0) {  # Si el contador de registros no es par
  17.         chomp $linea;               # Quitamos el carácter fin de línea
  18.         $numeros .= $linea;         # Guardamos la nueva línea de números
  19.     }
  20. }
  21.  
  22. print "$numeros\n"; # 123456789178923123456789178923
  23.  
  24. __DATA__
  25. >numeros
  26. 12345
  27. 67891
  28. 78923
  29. >letras
  30. adfjsfdaf
  31. asfdgsdfg
  32. safaadfgd
  33. >numeros
  34. 12345
  35. 67891
  36. 78923
  37. >letras
  38. adfjsfdaf
  39. asfdgsdfg
  40. safaadfgd
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Vamos recorriendo todas las líneas. Si empieza por '>', incrementamos el contador. Si no, puede ser una línea que tengamos que almacenar o no. Eso lo sabremos si el contador es par. Si lo es, entonces le quitamos el carácter de fin de línea y agregamos la $linea al final de la de $numeros, que hará de almacén de todos los números leídos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
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