Unixには、ストリームで関係代数に似た操作を実行するためのいくつかのユーティリティがあります(grep
、、、、、に追加)。すぐに利用可能な(またはほとんどのLinuxディストリビューションにインストール可能な)グループ集約ユーティリティはありますか?join
cut
awk
目的は、次のように、ある列にいくつかのキーがあり、他の列にいくつかの値を持つファイルを取得することです。
foo.txt u1 394082
bar.txt u2 3948
frob.c u1 29322
そして、ある列には一意の値があり、もう一方の列にはいくつかの値のセットを含むファイルが出力されます。たとえば、3番目の列と2番目の列の合計は次のようになります。
$ aggregate --sum=3 --group-by=2 <data
u1 423404
u2 3948
そのようなユーティリティが存在しますか(Perl、Awkなど、1行は含まれていません)、またはまだ作成されていませんか?
答え1
他のStackOverflowの質問でこの答えを見つけたようですが、「q」がこの目的に非常に役立つことがわかりました。https://github.com/harelba/q。
たとえば、サンプル目標は次のように達成できます。
$ q "select c2, sum(c3) from data group by c2"
u1 423404
u2 3948
sqliteをバックエンドとして使用するため、さまざまなsqlite関数を使用して計算できます。
答え2
いくつかの制限があります。GNU Recutilsこれは可能です。まず、TSVではなくCSVファイルでなければなりません(RecutilsはTSVファイルが好きではないようです)、ヘッダーが必要です。しかし、私はこれを行うことができます:
csv2rec foo.csv |recsel -G user -p 'user,sum(size)' |rec2csv
これがPerlやAwk one-linerより良いか悪いかはわかりません。
答え3
awk 1行が含まれていない場合は、おそらく次のシェル(bash / ksh)1行が欲しいでしょう:
sort -k2 data | ( while read c1 c2 c3; do if [ "$prev" = "$c2" ]; then
sum=$(expr $c3 + $sum); else if [ $prev ]; then echo $prev $sum; fi;
sum=$c3; prev=$c2; fi; done; echo $prev $sum)
そして(それぞれのグループ化と合計のために)ここで使用される興味深い要素は、sort
whileexpr
内の読み取りステートメントです。括弧は、ローカライズ$prev
と変数$sum
に必要なサブプロセスを作成します。