コピペコードで快適生活

明日使えるソースを自分のために

シェルでクロス集計するメモ

クロス集計をBash(とawk)だけで実装した話 より学んだことメモ

処理の流れ

1.必要なカラムの抽出
2.クロス集計の行と列の要素を取り出す。

# クロス集計表の行になる部分を抽出してユニーク化&ソート
cat table.csv | cut -f 1 -d , | sort -u > rowname.txt

# クロス集計の列になる部分を抽出、改行をタブに変えて縦横変換
cat table.csv | cut -f 2 -d , | sort -u | gtr '¥n' '¥t' > header.txt

# cutコマンド補足
cut -f {取り出したい項目} -d {区切り文字}

3.awkでファイル分割する。

cat table.csv
a,ice,130
a,ice,180
b,juice,120
b,ice,130
i,oreo,210
i,oreo,210
i,oreo,210

# awkで分割した結果をファイル出力できる
cat table.csv | gawk -F, '{print > "split_"$2}'

ls
split_ice	split_juice	split_oreo	table.csv

4.awkで集計する
5.sortでソート

ls | grep "split_" | gsed -e 's/split_//' | while read file; do gawk -F, '{a[$1]+=$3;}END{for(i in a)print i","a[i];}' split_${file} | sort -k 1 > sort_${file}; done

とか

gawk '{print FILENAME","$0}' split_* | gsed 's/split_//' | gawk -F, '{a[$1","$2]+=$4}END{for(i in a)print i","a[i];}' | sort -t, -k1,2 | gawk -F, '{print $2","$3 > "sort_"$1}'

6.2で取り出した行の要素と5の結果をJOIN

# joinできなかったキーも含めて出力し、空行は0で埋める
ls | grep sort_ | gsed 's/sort_//' | while read file; do join -t ',' -1 1 -2 1 -a 1 rowname.txt sort_${file} | gawk -F, '{print $2}' | gsed 's/^$/0/g' > split_sum_${file}; done

cat split_sum_juice
0
120
0

# joinコマンドメモ
# -t 区切り文字を指定
# -1 1番目のファイルで結合キーに使う項目番号
# -2 2番目のファイルで結合キーに使う項目番号
# -a 1 LEFT JOIN (未指定の場合はINNNER JOIN)
# -a 2 RIGHT JOIN
join -t ',' -1 1 -2 1 -a 1 rowname.text sort_${file}

7.paste と cat でマージしてリストを表に加工

# pasteで列同士を結合する
cp header.txt sum_result.txt
paste rowname.txt split_sum_* >> sum_result.txt


すっかりスルー気味でしたが、クロス集計用のコマンドがあります。 – 上田ブログ