今回も前回に続いてデータの整形処理です。前回は一列しかないデータでしたので処理も簡単でした。
一列しかなければAWKを使わなくてもよさそうです。今回は複数列のデータを扱います。表計算ソフトから書き出したデータを利用する場合にはAWKが役立つはずです。

今回もこれまで同様にサンプルで利用するファイル・ディレクトリはデスクトップのsampleディレクトリとしています。デスクトップにsampleディレクトリがない場合は作成しておいてください。(コマンド入力ならmkdir ~/Desktop/sampleとして作成することができます)
また、カレントディレクトリも上記の場所になります。cd ~/Desktop/sampleのようにコマンドを入力してカレントディレクトリを変更しておけばよいでしょう。

○データをまとめる

まず、必要なデータを用意しましょう。前回のデータに加えてpi2.txt, pi3.txtファイルを用意します。これらのデータもラズベリーパイ等IoTデバイスで計測した冷蔵庫などの温度データだと考えてください。pi1.txt,pi2.txt,pi3.txtファイルの内容は以下のようになっています。計測データの場合、機器のトラブルやメンテナンス等で欠損データが含まれることがありますが、この段階では欠損データはないものとします。


pi1.txt

6
8
10
9
6
5
3
0
-3
-8

pi2.txt

-1
2
7
10
9
10
7
5
3
-2

pi3.txt

-5
2
0
4
8
10
15
8
3
6

これら3つのファイルに分かれているものを1つのファイルにまとめます。まとめるには以前にもやったpasteコマンドを使います。3つのファイルを列として連結してdata.txtというファイルを作成します。この処理は以下のコマンドになります。

paste pi1.txt pi2.txt pi3.txt > data.txt

連結する前のデータが個別のファイルに分かれておらず、1つのファイルに複数の計測データが行単位で記録されている場合もありえます。

機器1の計測データ1
機器2の計測データ1
機器3の計測データ1
機器1の計測データ2
機器2の計測データ2
機器3の計測データ2
   :
機器1の計測データN
機器2の計測データN
機器3の計測データN

先ほどのpi1.txt~pi3.txtの内容で示すと以下のようになっているということです。

pi_all.txt

6
-1
-5
8
2
2
10
7
0
9
10
4
6
9
8
5
10
10
3
7
15
0
5
8
-3
3
3
-8
-2
6

このようなデータの場合でもpasteコマンドを使えば列単位に整形することができます。今回は3つの機器からのデータで3列にすれば良いので以下のようにコマンドを入力します。pasteコマンドの後の-がポイントで、列の数だけ指定します。保存する場合はリダイレクト(>)を使えばよいでしょう。

cat pi_all.txt | paste - - -

○列データのピックアップ

 前回のデータは1列しかありませんでしたが、今回は3つの列があります。列のピックアップ方法は前回と同じ$1,$2のように$の後にピックアップしたい列番号を指定します。

 まず、data.txtの2列目だけを表示してみます。printの後に$2を指定します。

awk '{print $2}' data.txt

1列目と3列目を表示したい場合は以下のように指定します。

awk '{print $1,$3}' data.txt

列の間を,にしたい場合は以下のように指定します。このようにすればCSV形式として保存することもできます。

awk '{print $1 "," $3}' data.txt

今回は列数が3と決まっていたので楽ですが、場合によっては列の数がわからない場合があります。そのような時に最後の列データを取り出したい場合は困ってしまいそうです。が、都合のよいことにAWKでは手軽に最終列を指定することができます。最終列は$NFでアクセスすることができます。

awk '{print $NF}' data.txt

最終列は$NFで指定できますが、最終列より1つ前の列を指定するには、どうしたらよいのでしょうか。この場合計算式を使って指定することができます。1つ前の列なので以下のように$(NF-1)と指定します。
今回の例では2列目のデータがピックアップされ表示されます。

awk '{print $(NF-1)}' data.txt

○条件付きで列データをピックアップ

 次に条件を指定して列データをピックアップしてみましょう。条件については前回説明したので、そちらを参照してみてください。
まず、負数のみピックアップしてみます。前回と異なり列が3つありますので、どの列の値が不数なら表示するのかを決めておきます。ここでは2列目が負数の場合、該当行を表示します。以下のようなコマンドになります。

awk '$2<0 {print}' data.txt

1行目を判断対象にする場合は$2を$1に、3行目なら$2を$3にします。実際に変更して試してみてください。

次に1列目と2列目の両方が負数の場合のみ該当行を表示してみます。この場合、複数の条件を指定することになります。複数条件は&&を使っていくつでも指定することができます。
1列目と2列目が負数の場合のみ該当行を表示するには以下のようにします。

awk '$1<0 && $2<0 {print}' data.txt

該当行の行番号を表示したい場合は以下のように指定します。

awk '$1<0 && $2<0 {print NR ":",$0}' data.txt

○四則演算を行う

 次に列の値に対して四則演算を行ってみましょう。最初の列に100を加算した結果を表示してみます。このような場合$1に対して単純に+100を指定するだけです。普通の計算式を指定できます。

awk '{print $1+100}' data.txt

2列目の値を100で割る場合は以下のようになります。

awk '{print $2/100}' data.txt

3列目の値を100倍するには以下のようになります。

awk '{print $3*100}' data.txt

1~3列(横列)の合計値を一番右側の列として表示するには以下のように指定します。行単位での列の合計が簡単に出せます。

awk '{print $0 "\t= " $1+$2+$3}' data.txt

1~3列(横列)の平均値を出したい場合は合計値を3で割ります。

awk '{print $0 "\t= " $1+$2+$3 "\t" ($1+$2+$3)/3}' data.txt

列の数がわからない場合は変数NFに処理する行内にある列の総数が入っています。
これを使った場合は以下のようになります。

awk '{print $0 "\t= " $1+$2+$3 "\t" ($1+$2+$3)/NF}' data.txt

剰余(割り算の余り)を求めたい場合は%を使います。以下の例では1列目の値と2との剰余を求めています。

awk '{print $3%2}' data.txt

.
編集部おすすめ