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
He
Wert (Spalte 8) - Wie viele hatten einen
Ho
Wert (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 perl
davon ausgegangen wird, dass infile
der 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, awk
die 4 Arrays verwendet, um die 4 benötigten Informationen zu zählen. Die Ausgabe von awk
wird dann in eingespeist, column
wodurch 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