• Publicidad

Extraer ciertas columnas de un archivo

Perl aplicado a la bioinformática

Extraer ciertas columnas de un archivo

Notapor abraham03 » 2017-12-30 20:54 @912

Hola.

Tengo este script que cuando lo hice se me olvidó escribir el código que omitiera la primera línea con un comentario

#Constructed from biom file

y que la segunda línea que también tiene una almohadilla

#OTU ID name_column1 name_column2 name_columnx... name_columnN

sea usada como variable.

El script funciona solo si elimino el comentario manualmente del archivo de entrada y no he podido agregar una línea que elimine el primer comentario y use todo lo demás.

He intentado agregar

if ($_=~ m/#Constructed from biom file/g) { next; }

en diferentes partes del script pero no me funciona.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use Getopt::Long;
  5. use Data::Dumper qw(Dumper);
  6. use List::MoreUtils qw(uniq);
  7. use List::Util qw(sum);
  8.  
  9. my ( $search_label, $infile_taxon, $infile_list, $output_file );
  10.  
  11. GetOptions(
  12.     'i=s' => \$infile_taxon,
  13.     'l=s' => \$infile_list,
  14.     's=s' => \$search_label,
  15.     'o=s' => \$output_file,
  16. );
  17.  
  18. #--------------------------- Subrutina de extracción para 2 arrays de lista de bacterias y taxones -------------------------------------------------------------
  19.  
  20. sub match_genera {
  21.     my ( $List_File, $Taxon_File ) = @_;
  22.     my @lista_genera = @{$List_File};          # desreferencia y copia cada array
  23.     my @taxon_qiime  = @{$Taxon_File};
  24.     my (@extract);
  25.     foreach (@lista_genera) {
  26.         my $unit = $_;
  27.         chomp $unit;
  28.         my @match = grep ( /$unit/, @taxon_qiime );
  29.         push( @extract, @match );
  30.     }
  31.     return @extract;
  32. }
  33.  
  34. #-------------------------------------------------------------------------------------------------------------------------------------
  35.  
  36. open INFILE_TAXONOMY, '<', "$infile_taxon" or die $!;
  37. open LIST_BACTERIA,   '<', "$infile_list"  or die $!;
  38. open OUTPUT,          '>', "xfile2.txt"    or die $!;
  39.  
  40. chomp( my @sample_names = split '\t', <INFILE_TAXONOMY> );
  41.  
  42. shift @sample_names;
  43. unshift @sample_names, '#Genera';
  44.  
  45. my ( @ToExtract, @no_match, @filter, @filter_columns );
  46.  
  47. # si ingresamos un -s
  48. if ($search_label) {
  49.     my @wanted = split( /\,/, $search_label );
  50.     unshift @wanted, '#Genera';
  51.     @wanted = uniq(@wanted);
  52.  
  53.     foreach my $wanted_in (@wanted) {
  54.         if ( my @match = grep ( /$wanted_in/, @sample_names ) ) {
  55.             push( @ToExtract, @match );
  56.         }
  57.         else {
  58.             push( @no_match, $wanted_in );
  59.         }
  60.     }
  61.  
  62.     if ( grep { defined($_) } @no_match ) {
  63.         print "\nSamples No Found: @no_match\n\n";
  64.     }
  65.     print join "\t", @ToExtract, "\n";
  66. }
  67.  
  68. # si queremos toda la tabla
  69. else {
  70.     @ToExtract = @sample_names;
  71.     print join "\t", @ToExtract, "\n";
  72. }
  73.  
  74. # Extraer los valores de cada línea para cada variable
  75. #my %row;
  76. while (<INFILE_TAXONOMY>) {
  77.     my %row;
  78.     @row{@sample_names} = split "\t";
  79.     @filter = join "\t", @row{@ToExtract};
  80.     push( @filter_columns, @filter );          # ahora ya se puede usar con la
  81. }
  82.  
  83. my @list;
  84. foreach (<LIST_BACTERIA>) {
  85.     if   ( $_ =~ m/^#|^$/ ) { next; }
  86.     else                    { push @list, $_ }
  87. }
  88. my @filter_list = uniq(@list);
  89.  
  90. my @last = match_genera( \@filter_list, \@filter_columns );
  91.  
  92. my ( @genera_taxon, @genera_final );
  93. foreach (@last) {
  94.     @genera_taxon = ( $_ =~ m/;D_5__(\w.*)/g );
  95.     foreach (@genera_taxon) {
  96.         if   ( $_ =~ m/^$/g ) { next; }
  97.         else                  { push @genera_final, $_; }
  98.     }
  99. }
  100.  
  101. foreach (@genera_final) {                      # divide la línea en múltiples variables
  102.     chomp;
  103.     my @val = split( /\t/, $_ );
  104.     foreach ( $val[1] ) {
  105.         if   ( $_ == 0 ) { next; }
  106.         else             { print join "\t", @val, "\n"; }
  107.     }
  108.  
  109. }
  110.  
  111. close INFILE_TAXONOMY;
  112. close LIST_BACTERIA;
  113. close OUTPUT;
  114.  
  115. exit;
  116.  
Coloreado en 0.007 segundos, usando GeSHi 1.0.8.4

por lo cual rehice el script que me elimina la primera línea y me aísla los datos restantes para usarles:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use strict;
  2. use warnings;
  3. use List::MoreUtils qw(uniq);
  4. use Data::Dumper qw(Dumper);
  5.  
  6. #--------------------------- Subrutina de extracción para 2 arrays de lista de bacterias y taxones -------------------------------------------------------------
  7. sub match_genera {
  8.     my ( $List_File, $Taxon_File ) = @_;
  9.     my @taxon_qiime  = @{$Taxon_File};
  10.     my @lista_genera = @{$List_File};          # desreferencia y copia cada array
  11.     my ( @match, @extract, @genera_clean );
  12.  
  13.     foreach (@taxon_qiime) {
  14.         my @generas_taxon = ( $_ =~ m/;D_5__(\w.*)/g );
  15.         foreach (@generas_taxon) {
  16.             if   ( $_ =~ m/^$/g ) { next; }
  17.             else                  { push @genera_clean, $_; }
  18.         }
  19.     }
  20.  
  21.     foreach (@lista_genera) {
  22.         my $list_unit = $_;
  23.         chomp $list_unit;
  24.         @match = grep ( /$list_unit/, @genera_clean );
  25.         push( @extract, @match );
  26.     }
  27.     return @extract;
  28. }
  29.  
  30. #------------------------------------------------------- ARCHIVOS ---------------------------------------------------------------------
  31.  
  32. open INFILE_TAXONOMY, '<', "lista_1.txt" or die $!;
  33. open LIST_BACTERIA,   '<', "lista_2.txt" or die $!;
  34.  
  35. my ( @lista_bacteria, @taxon, @sample_names );
  36.  
  37. # -------------------------------------------------------------TAXON -------------------------------------------------------------
  38. foreach (<INFILE_TAXONOMY>) {
  39.     chomp;
  40.     if    ( $_ =~ m/^$|Constructed from biom file/g ) { next; }
  41.     elsif ( $_ =~ s/OTU ID/Genera/g )                 { push @sample_names, $_; }
  42.     else                                              { push( @taxon, $_ ); }
  43. }
  44.  
  45. # -------------------------------------------------------------LIST -------------------------------------------------------------
  46. foreach (<LIST_BACTERIA>) {
  47.     if   ( $_ =~ m/^$|^#/g ) { next; }
  48.     else                     { push @lista_bacteria, $_ }
  49.  
  50. }
  51. my @filter_list = uniq(@lista_bacteria);
  52.  
  53. # -------------------------------------------------------------------------------------------------------------------------------
  54.  
  55. my @match_all = match_genera( \@filter_list, \@taxon );
  56.  
  57. unshift @match_all, @sample_names;
  58.  
  59. foreach (@match_all) {
  60.     print "$_\n";
  61. }
  62.  
  63. # agregar aquí el siguiente código pero para usarse con un array
  64. # supongamos que quiero extraer @wanted = qw(name_column1, name_column3)
  65. #while ( <INFILE_TAXONOMY> ){
  66. #my %row;
  67. #@row{@sample_names} = split "\t";
  68. #@filter= join "\t", @row{@ToExtract};
  69. #push (@filter_columns, @filter); # ahora ya se puede usar con la
  70. #}
  71.  
  72. close INFILE_TAXONOMY;
  73. close LIST_BACTERIA;
  74. exit;
  75.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Sin embargo, el resultado del anterior script es un array (@match_all), y no he podido agregarle el siguiente código, el cual me extrae únicamente las columnas que quiero (en el primer script es "-s name_column1, name_column2, name_columnX " para extraer esas tres columnas).

Me agradaría poder saber cómo uso el siguiente código con un array en lugar de <INFILE>:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. while (<INFILE_TAXONOMY>) {
  2.  
  3.     my %row;
  4.     @row{@sample_names} = split "\t";
  5.     @filter = join "\t", @row{@ToExtract};
  6.     push( @filter_columns, @filter );          # ahora ya se puede usar con la
  7. }
  8.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Intenté algo así:

my %row;
@row{@match_all} = split "\t";

para asignar los valores obtenidos del array y poder acceder a ellos cuando deseo buscar una columna, pero al imprimir con Dumper, para saber el orden me dio algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'Rhodococcus  0.00240865      0.0013441109    0.0' => undef,
          'Mycobacterium        0.00240818865   0.002309882217  0.0' => undef,
          'Gordonia     0.0     0.0     0.00140449438202' => undef,
          'Ornithinimicrobium   0.0006959663    0.0     0.0' => undef,
          'Dietzia      0.0150511739916 0.0311778290993 0.00140449438202' => undef,
          '#Genera      sample1 sample2 sample3' => undef
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

cuando creo que lo correcto sería algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          '#Genera' => 'Rhodococcus',
          'sample1' => '0.00240865',
          'sample2' => '0.0013441109',
          'sample3' => '0.0'
        };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Creo que aquí está mi error, el cual no he podido solucionar, ¡¡¡ debería de obtener cada columna como un valor !!!

Los archivos de entrada son dos listas en archivos txt; la primera está separada por tabuladores (\t) y la segunda es una lista la cual contiene nombres que va a buscar y extraer en la primera lista:
lista1.txt
(4.37 KiB) 182 veces

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. #lista2
  2.  
  3. Gordonia
  4. Mycobacterium
  5. Ornithinimicrobium
  6. Marinobacter
  7. Pseudoalteromonas
  8. Pseudomonas
  9. Halomonas
  10. Alcanivorax
  11. Acinetobacter
  12. Shewanella
  13. Pseudidiomarina
  14. Microbulbifer
  15. Bacillus
  16. Microbacterium
  17. Achrornobacter
  18. Coryneformes
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

El archivo de salida sería algo así: Si ingresamos la opción name_column1, name_column3 se obtiene los nombres que fueron encontrados con sus respectivos valores separados por un tabulador en cada columna:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. #Genera name_column1    name_column3   
  2. Gordonia        0.00301023479831        0.00140449438202       
  3. Mycobacterium   0.00240818783865        0.0    
  4. Ornithinimicrobium      0.000602046959663       0.0    
  5. Pseudomonas     0.367850692354  0.254213483146 
  6. Halomonas       0.000602046959663       0.00140449438202       
  7. Acinetobacter   0.00301023479831        0.00561797752809       
  8. Bacillus        0.0626128838049 0.00280898876404       
  9. Klebsiella      0.0138470800722 0.00280898876404       
  10. Lactobacillus   0.000602046959663       0.0    
  11. Acinetobacter   0.00301023479831        0.00561797752809       
  12. Gordonia        0.00301023479831        0.00140449438
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Me agradaría saber cualquier sugerencia, ya lo he intentado varios días y no he podido.

¡¡¡ Gracias !!!
abraham03
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2016-08-05 15:52 @703

Publicidad

Re: Extraer ciertas columnas de un archivo

Notapor explorer » 2017-12-31 21:39 @943

El problema es el siguiente: si el usuario te solicita extraer el sample name_column3, tu debes calcular qué número de campo debes extraer del archivo de taxones.

Es decir, si name_column3 es el campo número 4, ese es el número que debes guardar, para luego, en cada línea de taxones, sacar esa columna.

Por defecto, Perl no sabe qué los registros se componen de campos, ni qué nombre tienen esos campos.

Una opción sería, desde luego, usar un hash para dar un nombre a cada columna:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. %hash (
  2.    'ID' => 1,
  3.    'name_column1'       => 2,
  4.    'name_column2'       => 3,
  5.    'name_column3'       => 4,
  6. );
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

pero el caso es que no te hace falta: con recordar el número de las columnas que hay que extraer, y en qué orden (te lo da el usuario), te vale.

Entonces, por cada taxón leído, lo spliteamos, y sacamos los campos indexados por los números de las columnas que nos interesan.

Para sustituir el while() por el recorrido de un array, puedes usar un for() o foreach() de ese array.
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: Extraer ciertas columnas de un archivo

Notapor abraham03 » 2018-01-05 03:19 @179

Muchas gracias, como siempre muy amable. Realmente me puse un poco en el sentido "Lo tengo que resolver" y por ello no había respondido. Afortunadamente (después de muchos ensayos y errores) lo logré :D :D Mil gracias.
abraham03
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2016-08-05 15:52 @703


Volver a Bioinformática

¿Quién está conectado?

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

cron