連想配列について

さて、私が好んで多用する連想配列のお話です。
AWKの配列変数は連想配列しか搭載していません。何故ならAWKのデータ型は基本的に文字列だけだからです。AWK内部では、数値は数字の文字列として扱われます。

それでは、連想配列のお話の始まり始まりぃ〜〜〜
・・・と言っても、連想配列の詳細な説明をここでお話しするつもりはありません。私がいつも使っている手法をご紹介します。
その手法とは・・・
多くのテキストデータから幾つかのキーワードの出現頻度を集計する方法をご紹介いたします。
仮想のデータ処理では説明しにくいので、ここでは気象協会の地震データから震源地別マグニチュード別の地震発生頻度集計を例とします。

「気象協会の地震データ」とは、こちらのサイトから得た地震発生日時ごとのデータとします。
私は、表示したページをコピペして、地震発生日時ごとにファイルに保存しました。
それらのファイルの一部に以下のような箇所があります。

発生時刻 6月20日 1時31分 
震源地 福島県沖 
位置 緯度 北緯37.5度 
経度 東経141.4度 
震源 マグニチュード M3.6 
深さ 約20km 
これらのテキストの中から、震源地(上記例では「福島県沖」)と、マグニチュード(上記例では「3.6」)を抜き出し集計しましょう。
スクリプトの概要(流れだけ)は以下のとおりです。コメントを入れておきました。
BEGIN {
  # 連想配列に全てのファイルの震源地とマグニチュードを集計する
  for (i = 1; i <= f_num; i++) {		# ファイルごと読込ループ
    while (getline < arr[i] > 0) {		# ファイル内行読み込みループ
      sin = …;				# 震源地切出し
      mag = …;				# マグニチュード切出し
      arr[sin "," mag]++;			# 配列変数に集計(震源地とマグニチュードをカンマで連結)
    }
  }
  # 集計データをファイル出力
  for (str in arr) {				# 配列変数から集計内容を読みだすループ
    printf("%s,%d\n", str, arr[str]) > out_file;	# 震源地、マグニチュード、頻度をファイル出力
  }
}
3 〜 9 行は保存しておいた気象協会データファイルごとの集計ループです。
4 〜 8 行ではそれぞれのファイルから 1 行ごとに読み込んで、震源地とマグニチュードを切り出します。
そして、切り出した震源地とマグニチュードの文字列をカンマを挟んで連結します。この文字列を連想配列で頻度集計します。
その方法は、配列変数 arr の添え字とした配列要素をインクリメント(+1カウント)しているだけです。
11 〜 13 行では集計した配列変数から要素ごとに結果をファイル出力しています。
各要素は添え字とした文字列(震源地とマグニチュード)とカウントされた配列要素の値(頻度)をカンマで挟んで出力しています。
結局ファイルには、震源地、マグニチュード、発生頻度がカンマで区切られたデータ(CSV形式データ)として出力されます。
実行結果の一部をご覧ください。
茨城県沖,3,42
茨城県沖,4,138
茨城県沖,5,78
茨城県沖,6,23
茨城県沖,7,3
茨城県南部,3,34
茨城県南部,4,28
茨城県南部,5,8
茨城県北部,2,1
茨城県北部,3,71
茨城県北部,4,63
茨城県北部,5,12
茨城県北部,6,2
ご覧のようにCSV形式として出力されました。
このデータを Excel で読み込んでピボットテーブルで集計しなおすと下図のようになります。
データさえ手に入れれば、あっという間に集計出来るのです。

Excel で読み込んだデータ(ピボットテーブルの一部です)
Excelのピボットテーブル

以上のとおり、集計したいキーワードを添え字とした配列変数をインクリメントすることを繰り返すだけで、そのキーワードの出現頻度を集計出来るのです。
どうです。出現頻度集計って簡単でしょ!!


参考:
「for (変数 in 配列)」は、「配列変数の各要素ごとに添え字を変数に読みだす」という動作をします。
このとき、読みだす順番はソートされていませんし、配列変数に記憶した順でもありません。ご注意ください。
連想配列のデータ構造はハッシュテーブルですので、数学的な意味での読み出し順はあります。・・・が、私たちにはランダムにしか見えません。

なお、私はこの連想配列の要素をソートする関数を作成し、この関数を通して出力するようにしています。何かの折にご紹介しましょう。

<-->

戻る