データクレンジングをMコマンドとbashでやってみる

#データクレンジングで何をしたいんですか？
データクレンジングとはその名の通りデータを”**きれい**”にすることです。データクレンジングの目的は、データ分析をするための最低限の作業条件と捉えましょう。データクレンジングが必要なデータは、主に次のパターンによく出くわします。
1.データが構造化されていない（TVS,CSVの形式でなくスペース、カッコなどで構造が表現されている）
2.表形式でデータが保有されている
3.マスターテーブルの更新に合わせたデータ更新がされていない

特に政府統計（[e-stat](http://e-stat.go.jp/SG1/estat/eStatTopPortal.do)）は2.と3.の作業がメインです。2.表形式でデータが保有されているというのは、クロス集計表の形式をイメージしてください。横持ち形式とも言います。同じ分類に属する項目を一つの項目にまとめて表示する表形式への変換を縦持ち形式への変換といいます。エクセルの手作業でもできなくない作業ですが、クレンジングの方針が変わった場合やクレンジングのミスが発覚した場合には手戻りが発生するのでコマンド群で処理したいところです。この記事では、2.表形式でデータが保有されている場合の表形式の変換について説明します。

【横持ち形式のデータ例1】

| 企業ID     |       Q1  |    Q2   | Q3 | Q4
|:-----------------:|:------:|:------:|:------:|:--------:|
| AAAAA         |      300         |     100     |200 |400 |


【縦持ち形式のデータ例2】

| 企業ID     |      四半期  |   売上高     |
|:-----------------:|:------------------:|:-----------:|
| AAAAA         |            Q1 |        300     |
| AAAAA         |            Q2 |       100         |
| AAAAA         |            Q3 |       200         |
| AAAAA         |            Q4 |       400         |

#どうやって横持ち→縦持ちに変換するのですか？
　表形式の変換の前提として、余分な行や列は削除して表形式のみの形にしてください。e-statの素晴らしく作りこまれた表は自動で削除しにくいものが多いので、少数のデータであれば手動で不要な列や行を削除してしまいましょう。エクセル形式で多数のシートを含むファイルのクレンジング処理の方法は次回書きたいと思います。
　純粋に横持ち形式のデータが得られたら、横持ち形式の項目名を列として挿入した表を作ることが第1ステップです。上の表の例で言えば、Q1という要素を300の左隣に挿入して、企業IDの右隣りに項目名「四半期」を記入してあげればよいということです。第2ステップとしては横持ち形式で「Q１」と記載されている部分は売上高に変更してあげます。これで、Q1のみについては縦持ち形式にできました。同じようにQ2～Q4についても下記と同じ形式の表を作成します。

【横持ち形式を縦持ち形式に変換した表（結合前）】

| 企業ID   | 四半期 |       売上高 ~~Q1~~  |
|:----------:|:-------:|:------:|:------:|
| AAAAA        | Q1 |      300         |  

| 企業ID   | 四半期 |       売上高 ~~Q2~~  |
|:----------:|:-------:|:------:|:------:|
| AAAAA        | Q2 |      100         |  

| 企業ID   | 四半期 |       売上高 ~~Q3~~  |
|:----------:|:-------:|:------:|:------:|
| AAAAA        | Q3 |      200         |  

| 企業ID   | 四半期 |       売上高 ~~Q4~~  |
|:----------:|:-------:|:------:|:------:|
| AAAAA        | Q4 |      400         |  

最後のステップでQ1からQ4までの上記4つの表を縦方向に結合することで【横持ち形式のデータ例1】のような表を作ることができるようになります。
　アルゴリズムに落とし込んで考えると流れは次のようになります。
1.横持ち形式の最初の列を取得
2.縦持ちにする項目名をもつ列を順次取り出した表を作る
3.縦持ち形式の場合の列名と対応する項目名を取り出した表に付与する
4.すべての縦持ちにする項目について3.までの作業が終了したら、表を結合する。

#どうやって実装するのですか？
Mコマンドとbashを使います。Mコマンドとは、[NYSOLのホームページ](http://www.nysol.jp/)を引用すると、

>大規模な表構造データ（CSVデータ）を効率よく処理する目的で開発されたオープンソースのコマンド群である。一般のPCでも数千万件〜数億件のCSVデータを処理できる。

というものです。CSVファイルの効率的な処理を実現するコマンド群です。上記のアルゴリズムの構築例を書くと次のようになります。今回サンプルとして利用しているデータは[観光地域経済調査](http://www.mlit.go.jp/kankocho/siryou/toukei/kouzou.html)の主な事業の利用者数を示すものです。エクセルファイルから不要な列や行を取り除いたcsvファイルを用意しておきます。（エクセルからcsvファイルにクレンジングする方法は次回記載）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/169281/39a9e31d-d78a-a192-a951-c9da0ca02230.png)

縦持ち形式にするためのコードは次ようになります。

```bash:CleanData.sh
#!/bin/sh

#ディレクトリの指定
DT=/home/<<※ご自身のユーザー名を記入してください>>/デスクトップ
Tmp=${DT}/tmp
Out=${DT}/out

#作業用ディレクトリの作成、Tmpは一時的に中間ファイルを保管する場所、Outはクレンジング結果を保管する場所
mkdir -p ${Tmp}
mkdir -p ${Out}

#データクレンジングの本体コード
clean_data(){

itemList=`head -n1 sample.csv | cut -d',' -f2- | sed -e "s/,/ /g"`

for item in ${itemList};do
	mfldname f=主な事業:集計年月 i=${DT}/sample.csv |
	mcut f=集計年月,${item} |
	msetstr a=事業区分 v=${item} |
	mfldname f=${item}:利用者数 |
	mcut f=集計年月,事業区分,利用者数 o=${Tmp}/xxx_${item}
done

#すべてのファイルを結合する
#集計年月、事業区分に総数があるため、行選択により削除する
#年号表記のものは西暦表記に置換する
mcat i=${Tmp}/xxx_'*' | 
mselstr -r f=集計年月 v=総数 | mselstr -r f=事業区分 v=総数 |
msed f=集計年月 c='平成23年' v='2011年' -g o=${Out}/trans_sample.csv

}

#データクレンジングを回すためのメイン関数
#便宜的にmainの中で関数を回すことで関数が増えた時にも対応できるようにしておく。

main(){
	clean_data
}
main

```
クレンジングのアルゴリズムを知っておくことでクレンジングへの耐性がつくことでしょう。