2012年8月1日水曜日

[Linux][LaTeX] awkを使ってLaTeXの表を書く

処理時間などの表を,LaTeXで書くのって結構めんどくさいんですよね.

もっといい方法があるかもしれませんが,awkの基本的な機能を使ってLaTeXの表を書く方法をメモしときます.



1. データファイルの用意

データファイルは,data1, data2とします.これを組み合わせてひとつの表にします.

data1:
1000 0.0007979870 987
2000 0.0014159679 1942
3000 0.0017130375 2857
4000 0.0019850731 3759
5000 0.0027661324 4628
6000 0.0034708977 5473
7000 0.0040469170 6282
8000 0.0047509670 7028
9000 0.0053861141 7776
10000 0.0058817863 8499

data2:
1000 0.0008270741 980
2000 0.0014939308 1943
3000 0.0025620461 2868
4000 0.0019671917 3746
5000 0.0026450157 4594
6000 0.0035498142 5421
7000 0.0042159557 6209
8000 0.0048799515 6986
9000 0.0057148933 7745
10000 0.0060670376 8470

ちなみに,これはクイックソートの処理時間と再帰呼び出しの回数です


2. joinコマンドでファイルを連結

次に,joinコマンドでファイルを連結します.

ファイルが2つだけのときは,次のようにすると連結できます.

$ join data1.dat data2.dat > join.dat

出力結果は,次のようになります.

$ cat join.dat
1000 0.0007979870 987 0.0008270741 980
2000 0.0014159679 1942 0.0014939308 1943
3000 0.0017130375 2857 0.0025620461 2868
4000 0.0019850731 3759 0.0019671917 3746
5000 0.0027661324 4628 0.0026450157 4594
6000 0.0034708977 5473 0.0035498142 5421
7000 0.0040469170 6282 0.0042159557 6209
8000 0.0047509670 7028 0.0048799515 6986
9000 0.0053861141 7776 0.0057148933 7745
10000 0.0058817863 8499 0.0060670376 8470


ファイルが3つ以上のときは,パイプを使って,

$ join data1.dat data2.dat | join - data3.dat | join - data4.dat .....

というふうに連結します.


3. awkでLaTeXのソースを出力

あとはとても簡単です.

列ごとの出力の間に,"&"を出力して,最後に"\\"を出力すればいいんです.

awkでは出力を列ごとに行うので,列を$1, $2, $3...で表します.

たとえば,join.datからデータ数と計算時間を得るには,$1,$2,$4が必要なので,

$ awk '{print $1 " & " $2 " & " $4 "\\\\"}' join.dat
1000 & 0.0007979870 & 0.0008270741\\
2000 & 0.0014159679 & 0.0014939308\\
3000 & 0.0017130375 & 0.0025620461\\
4000 & 0.0019850731 & 0.0019671917\\
5000 & 0.0027661324 & 0.0026450157\\
6000 & 0.0034708977 & 0.0035498142\\
7000 & 0.0040469170 & 0.0042159557\\
8000 & 0.0047509670 & 0.0048799515\\
9000 & 0.0053861141 & 0.0057148933\\
10000 & 0.0058817863 & 0.0060670376\\

これで完了です.

バックスラッシュ(\)はエスケープシーケンスなので,"\\"で表します.


4.データを粗くしたいとき

data1, data2ではデータを1,000ずつとっていますが,これを50,000までとったときなどはさすがに全部載せると長いですね.

そういう時は,剰余の演算を使って,awkに条件をつけます.

2,000ずつ出力するには,

$ awk '$1 % 2000 == 0 {print $1 " & " $2 " & " $4 "\\\\"}' join.dat
2000 & 0.0014159679 & 0.0014939308\\
4000 & 0.0019850731 & 0.0019671917\\
6000 & 0.0034708977 & 0.0035498142\\
8000 & 0.0047509670 & 0.0048799515\\
10000 & 0.0058817863 & 0.0060670376\\

こんな感じです.

1,000の時だけは特別に表示したいなんてときは,OR(||)も使って,こんな風にしてます.

$ awk '$1 % 2000 == 0 || $1 == 1000 {print $1 " & " $2 " & " $4 "\\\\"}' join.dat
1000 & 0.0007979870 & 0.0008270741\\
2000 & 0.0014159679 & 0.0014939308\\
4000 & 0.0019850731 & 0.0019671917\\
6000 & 0.0034708977 & 0.0035498142\\
8000 & 0.0047509670 & 0.0048799515\\
10000 & 0.0058817863 & 0.0060670376\\



5. おわりに

自分が最近やってみた方法を載せてみました.

この方法はめんどくさい感じがするので,データが少ないときは普通に書いたほうが楽かもしれないですね.

もうちょっとスマートなやり方があったらいいなー
と思ってます.