Analysieren einer Textdateitabelle und Aggregieren von Informationen

Analysieren einer Textdateitabelle und Aggregieren von Informationen

Ich habe eine lange Textdatei mit den folgenden, durch Leerzeichen getrennten Spalten:

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 

Ich möchte eine Tabelle erstellen, in der jede eindeutige ID zusammen mit den Zählungen für Folgendes aufgeführt ist:

  • Wie oft ist diese ID aufgetreten?
  • Wie viele dieser Reihen waren bestanden (Spalte 6)
  • Wie viele hatten einen HeWert (Spalte 8)
  • Wie viele hatten einen HoWert (Spalte 9)

In diesem Fall:

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

Wie kann ich diese Tabelle erstellen?

Antwort1

Eine Möglichkeit, bei der perldavon ausgegangen wird, dass infileder Inhalt Ihrer Frage vorhanden ist (die IDs werden in der Ausgabe nicht unbedingt in derselben Reihenfolge angezeigt, da ich sie mit einem Hash speichere):

Inhalt von 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 } };
}

Führen Sie es wie folgt aus:

perl script.pl infile

Mit folgender Ausgabe:

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

Antwort2

Hier ist eine Lösung, awkdie 4 Arrays verwendet, um die 4 benötigten Informationen zu zählen. Die Ausgabe von awkwird dann in eingespeist, columnwodurch die Spalten ordentlich ausgerichtet werden. (Beachten Sie, dass dies auch mit hätte erfolgen können awk. 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

Ausgabe:

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

verwandte Informationen