Analizar una tabla de archivo de texto y agregar información

Analizar una tabla de archivo de texto y agregar información

Tengo un archivo de texto largo con las siguientes columnas, delimitadas por espacios:

Id            Pos Ref  Var  Cn   SF:R1   SR  He  Ho NC       
cm|371443199  22  G     A    R   Pass:8   0   1  0  0       
cm|371443199  25  C     A    M   Pass:13  0   0  1  0
cm|371443199  22  G     A    R   Pass:8   0   1  0  0        
cm|367079424  17  C     G    S   Pass:19  0   0  1  0      
cm|371443198  17  G     A    R   Pass:18  0   1  0  0       
cm|367079424  17  G     A    R   Pass:18  0   0  1  0 

Quiero generar una tabla que enumere cada ID única junto con los recuentos de:

  • ¿Cuántas veces ocurrió esa identificación?
  • ¿Cuántas de esas filas pasaban (columna 6)?
  • ¿Cuántos tenían un Hevalor (columna 8)?
  • ¿Cuántos tenían un Hovalor (columna 9)

En este caso:

Id            CountId  Countpass   CountHe CountHO
cm|371443199   3        3          2        1
cm|367079424   2        2          0        2

¿Cómo puedo generar esa tabla?

Respuesta1

Una forma de usar perlasumir infiletiene el contenido de su pregunta (las ID no estarán necesariamente en el mismo orden en la salida porque uso un hash para guardarlas):

Contenido de script.pl:

use strict;
use warnings;

my (%data);

while ( <> ) { 

    ## Omit header.
    next if $. == 1;

    ## Remove last '\n'.
    chomp;

    ## Split line in spaces.
    my @f = split;

    ## If this ID exists, get previously values and add values of this
    ## line to them. Otherwise, begin to count now.
    my @counts = exists $data{ $f[0] } ? @{ $data{ $f[0] } } : (); 
    $counts[0]++;
    $counts[1]++ if substr( $f[5], 0, 4 ) eq q|Pass|;
    $counts[2] += $f[7];
    $counts[3] += $f[8];
    splice @{ $data{ $f[0] } }, 0, @{ $data{ $f[0] } }, @counts; 
}

## Format output.
my $print_format = qq|%-15s %-10s %-12s %-10s %-10s\n|;

## Print header.
printf $print_format, qw|Id CountId CountPass CountHe CountHo|;

## For every ID saved in the hash print acumulated values.
for my $id ( keys %data ) { 
    printf $print_format, $id, @{ $data{ $id } };
}

Ejecútelo como:

perl script.pl infile

Con la siguiente salida:

Id              CountId    CountPass    CountHe    CountHo   
cm|371443198    1          1            1          0         
cm|371443199    3          3            2          1         
cm|367079424    2          2            0          2

Respuesta2

Aquí hay una solución awkque utiliza 4 matrices para contar las 4 piezas de información que necesita. Luego, la salida awkse alimenta, columnlo que alinea muy bien las columnas. (Tenga en cuenta que esto también se podría haber hecho awkusando printf.)

awk 'NR>1 {
    id[$1]++
    if($6 ~ /Pass/) pass[$1]++
    if($8 ~ /1/) he[$1]++
    if($9 ~ /1/) ho[$1]++
} 
END {
   print "Id CountId Countpass CountHe CountHO"
   for(i in id)
      print i" "id[i]" "(pass[i]?pass[i]:0)" "(he[i]?he[i]:0)" "(ho[i]?ho[i]:0)
}' input.txt | column -t

Producción:

Id            CountId  Countpass  CountHe  CountHO
cm|371443198  1        1          1        0
cm|371443199  3        3          2        1
cm|367079424  2        2          0        2

información relacionada