次のファイルがあります。
2017-07-30 A
2017-07-30 B
2017-07-30 B
2017-07-30 A
2017-07-30 A
2017-07-30 C
2017-07-31 A
2017-07-31 B
2017-07-31 C
2017-07-31 B
2017-07-31 C
各行は、イベント(A、B、C)とイベントが発生した日付を示します。 1日に各タイプのイベント数を計算したいです。これはで行うことができ、sort file | uniq -c
出力は次のようになります。
3 2017-07-30 A
2 2017-07-30 B
1 2017-07-30 C
1 2017-07-31 A
2 2017-07-31 B
2 2017-07-31 C
しかし、各イベントタイプを列として使用したいと思います。
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
これを行うことができる非常に一般的なコマンドラインツールはありますか?必要に応じてすべてのイベントタイプ(A、B、C)を事前に知っていると仮定できますが、そうでない場合はそれがより良いです。繰り返しますが、各イベントが1日に1回以上発生すると仮定できますが(出力にゼロがないことを意味します)、これが必要でない場合はここで問題ありません。
答え1
「かなり一般的」に以下が含まれる場合GNUデータの混合、その後
datamash -Ws crosstab 1,2 < file
前任者。
$ datamash -Ws crosstab 1,2 < file
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
(残念ながら、Webサイトの形式はタブを保持しません。実際の出力はタブの整列です。)
答え2
アッ解決策:
awk '{ d[$1]; k[$2]; a[$2,$1]++ }END{
printf("%10s"," ");
for(i in k) printf("\t%s",i); print "";
for(j in d) {
printf("%-10s",j);
for(i in k) printf("\t%d",a[i,j]); print ""
} }' file
出力:
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
答え3
より短いバージョンでは、NULL値は0に割り当てられません。
perl -lane '
++$h{$i[!$h{$F[0]} ? @i : -1]=$F[0]}{$F[1]}}{
print join "\t", "\t", @h = sort keys %{ +{ map { map { $_ => 1 } keys %$_ } values %h } };
print join "\t", $_, @{$h{$_}}{@h} for @i;
' yourfile
perl -lane '
$i[@i]=$F[0] unless $h{$F[0]};
++$h{$F[0]}{$F[1]}}{
@h = sort keys %{ +{ map { map { $_ => 1 } keys %$_ } values %h } };
print join "\t", "\t", @h;
for my $date ( @i ) {
my $href = $h{$date};
print join "\t", $date, map { $href->{$_} || 0 } @h;
}
' yourfile
結果
A B C
2017-07-30 3 2 1
2017-07-31 1 2 2
データ構造:
%h
キーがA、B、Cなどである日付と値を含むハッシュサブハッシュでkeys
あり、その値はその特定の日付のそれぞれの数です。
%h = (
2017-07-30 => {
A => 3,
B => 2,
C => 1,
},
...
);
@i
日付が発生した順序で保存する配列です。@i
以前に見たことがない場合、または初めて見た場合にのみ、日付を配列にプッシュします。順序は配列の位置に応じて提供されます。@h
ハッシュのすべての「A」、「B」、「C」などのキーを合計した後、配列には独自のキーがあります%h
。
答え4
使用法: ./count.awk input.txt | column -t -n
#!/usr/bin/gawk -f
{
dates[$1] = $1;
events[$2] = $2;
numbers[$1][$2]++;
}
END {
num_dates=asort(dates);
num_events=asort(events);
for (i = 1; i <= num_events; i++) {
printf " %s", events[i];
}
print "";
for (i = 1; i <= num_dates; i++ ) {
printf "%s ", dates[i];
for (j = 1; j <= num_events; j++) {
printf "%s ", numbers[dates[i]][events[j]];
}
print "";
}
}
テスト:
入力する(テストが複雑)
2017-07-30 A
2017-07-30 D
2017-07-29 D
2017-07-30 B
2017-07-28 E
2017-07-30 B
2017-07-30 A
2017-07-30 A
2017-07-30 C
2017-07-31 A
2017-07-31 B
2017-07-31 C
2017-07-31 B
2017-07-31 C
出力
A B C D E
2017-07-28 1
2017-07-29 1
2017-07-30 3 2 1 1
2017-07-31 1 2 2