データの抽出と分析に適していないといわれていたMongoDBのデータを、RのためのUIであるExploratoryを使って分析してみた

いままでに、MongoDBのデータ分析に困ったことはありませんか？

一般的に、MongoDBのデータは、リレーショナルデータベースや表形式データと違うので、データが、よく階層になっていたり、入れ子構造になっていたり、配列を含んだりしていて、データの抽出や分析には適していないと言われています。でも、RのためのUIであるExploratoryを使えば、そんなMongoDBのデータでさえ簡単にインポートして、データを分析することができます。

Exploratoryの記事については、こちらでも詳しく書いています。

- [Rのフロントエンドということで話題になっている、Exploratoryの対話的なデータ分析環境で「ヨーロッパはほんとに女性が活躍しやすい社会か」どうか分析してみた](http://qiita.com/21-Hidetaka-Ko/items/a7e2e87f46f82915c356)
- [本当にITバブルなのか？？　RのフロントエンドExploratoryでユニコーン企業のデータを超簡単にスクレイピングしてきて、分析してみた](http://qiita.com/21-Hidetaka-Ko/items/b1b753a14362385021b6) 
- [テキスト・データを簡単にクリーン・アップしながらExploratoryのベータ版に世界中から登録してくれたユーザーの普段使っているデータ分析ツール上位ランキングを出してみた](http://qiita.com/21-Hidetaka-Ko/items/b6b90a5186d5f31b540a)  


##1. MongoDB Dataのデータをインポート


これから、レストランのデータが集められている標準的なMongoDBのデータベースを使います。データはこちらからダウンロードできます。[MongoDB website](https://docs.mongodb.org/getting-started/shell/import-data/)

- [MongoDB Example Dataset Import Instruction](https://docs.mongodb.org/getting-started/shell/import-data/)

Mongo DB のインポートダイアログを開いてください

New Data Frameメニューからデータを選んで、Import Remote Dataを選んでください。

<img width="628" alt="import-remote-data.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/ca132f96-743a-9071-b041-051145ef2368.png">



Mongo DBをクリックしてください。


<img width="1387" alt="mongo1.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/7508f457-2c82-641c-89f0-2b4307484420.png">


パラメータを設定してください

data frameの名前を入力してください。

Mongo DBの設定情報を入力してください。

- Host name
- Port number
- Database name
- Collection name
- Username
- Password
- Query - あなたが、特定のクエリを使っていない限り、デフォルトのままで大丈夫です。
- Flatten - 大抵の場合、デフォルトのままで大丈夫です。

注意：もし、MongoDBをローカルにインストールしている場合でも、ユーザーネーム、パスワードを指定した上での接続が必要になります。ユーザーネーム、パスワードなしでの接続はこれからのサポートしていく予定です。

![mongo3.png](https://qiita-image-store.s3.amazonaws.com/0/91522/34016767-0a36-8ff6-7f3a-4df69841712a.png)



Mongo DBのデータを見れるように、GET DATAボタンをクリックしてください。



大丈夫そうだったら、データをExploratoryにインポートするためにSAVEボタンをクリックしてください。

すると、このようにデータがサマリー画面に表示されます。


<img width="1432" alt="mongo4.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/95eb73ee-fe73-7ff3-8805-19e6dc4af115.png">


##2. 入れ子構造になっているデータをUnnestしよう

MongoDBのデータベースは、リレーショナルデータベースではないので、データがよく入れ子構造になっていることが多いです。このデータでも、grades列を見てみると、データタイプがlistになってますよね。

<img width="1432" alt="mongo4_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/3ebb6f9a-a17d-aee7-5942-a5c64f35558e.png">


テーブル画面に行くともう少し詳しく見ることができます。それぞれの日付に対して、レストランのgradesを持っている形になっています。

<img width="1232" alt="mongo5.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/288b4f32-470e-1ac0-3659-cbc196357714.png">


なので、この入れ子構造(nest)になっているのを、ほどいて（Unnest）、grade, score, date をそれぞれの行に落としこむ必要があります。Unnest関数を使うとそれをすることができます

grade列のヘッダーメニューからUnnestを選んでください。

<img width="1432" alt="mongo6.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/8f509cbf-ae53-69ae-43a1-b64975f37dd8.png">


すると、自動的にコマンドが入力されて、入れ子になっていたデータ構造がUnnestされて、date,grade,scoreの３つの列に分割されたのがわかりますね。

![mongo7.png](https://qiita-image-store.s3.amazonaws.com/0/91522/64c02e6e-8bca-4c42-4e18-839abade49d4.png)


テーブルviewでも同様に。

<img width="1232" alt="mongo8.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/015070d9-69cc-5dba-15c8-4f719c2ec3d4.png">

ところで、このaddress.coordは、経度と緯度を表しているんですね。このカラムもlistになっているので、またunnestして２つの行にわけることももちろんできるんですが、経度と緯度という列を使って、ビジュアライズすることもできます。

<img width="1225" alt="mongo12.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/d804bc12-fb09-2f00-dd1f-8f39b98f6acc.png">


そうするときは、いくつかやり方があるんですが、これから一番簡単な方法をご紹介します。

##3. データタイプがListになっている列から値を抽出しよう

＋アイコンを押すと出てくるドロップダウンメニューからMutateを選んでください。

<img width="1228" alt="mongo14.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/17023d22-35e2-56fd-236b-e5a061a1e621.png">


新しいカラムとしてlongitudeと入力したあとに、=を入力してください。

<img width="1228" alt="mongo15.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/21de1393-ec04-627e-ef8f-851f65b92c8d.png">


スペースをタイプすると、列と関数の一覧がレコメンドされます。Open Function Selectorでは、関数をタイプ別から検索することができます。クリックしてください。


<img width="1228" alt="mongo15.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/d8f3ed8f-9795-f027-8252-f261e714de17.png">




Listカテゴリーを選んでください。

<img width="950" alt="mongo16.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/f877d515-1058-2cbb-f94a-c87d0abd28b6.png">



すると、データタイプが、Listのものに対して使うことができる関数を見ることができます。そこから、list_extract関数を選んでください。

<img width="1088" alt="mongo18.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/284bd345-a798-16e8-5522-13170155d0a2.png">


Insert Functionをクリックしてください。

<img width="1088" alt="mongo19.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/7e12f96a-2958-8317-e747-47ccfb30f51a.png">


レコメンドされたリストからaddress.coord列を選んでください。

<img width="1229" alt="mongo20.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/c82d9ef4-26b6-b5ff-f8c1-d8b309897d47.png">


カンマの後に、1と入力してください。

```
mutate(longitude = list_extract(address.coord, 1))
```

同じように、latitudeの値を抽出するために、'mutate()'コマンドの中にlatitude列を加えてください。カンマの後に、2と入力してください。

```
mutate(longitude = list_extract(address.coord, 1), latitude = list_extract(address.coord, 2))
```

Runボタンを押してください。すると、いま作成したlongitude列とlatitude列ができているのがわかりますね。

<img width="1224" alt="mongo22.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/f385b13e-c75d-b7c3-ec3a-996cbcf882b6.png">



これでデータは充分です。経度と緯度の列ができたので、この２つを使って、データをビジュアライズ化してわかりやすくしてみましょう。

チャート画面に行って、チャートタイプでマップを選んで、Longitudeにlongitude列を、Latitudeにlatitude列を指定してください。

<img width="1234" alt="mongo23.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/72a103ce-97be-2030-51cc-81be7034e6d6.png">


あれ？　でも結果は少し変ですね。

<img width="1003" alt="mongo24.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/61e4fd47-b9ef-dc55-b01e-bc7e07bdcc5f.png">


boroughカラムを見てみると、レストランのほとんどは、マンハッタンとかブルックリンとかクイーンなどニューヨークの都市になっています。でも、マップを見てみると、ニューヨーク以外にもたくさんあるように見えますよね？

<img width="1204" alt="mongo25.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/7171a7ed-a649-91a1-ba6a-0628291169cb.png">


でもデータをズームしてみると、ほとんどのレストランはニューヨークに集中していることも確認できます。

![mongo26.png](https://qiita-image-store.s3.amazonaws.com/0/91522/b1d9742c-c82b-0dac-1daf-d8c33364a1ae.png)


これはつまり、いつかのレストランは間違った位置データを持っているということなんです。

##4. 四分位数範囲を計算して、外れ値を見つけて、取り除く

間違った位置データを除くためには、データの25%から75%の間を意味する四分位数範囲を計算する必要があります。quantile関数を使うと、引数で指定した、分位数を取得することができます。例えば、0.75なら第三四分位数を取得できます。四分位数範囲のことを英語で、interquartile rangeと呼ぶんですが、Rでは、その3文字をとったiqr関数を使うことで、データの四分位数範囲を取得できます。そして、四分位数範囲を取得すると、第三四分位数に対して、iqrの1.5倍を足したもののほうをupper_rangeという名前の列にして、第一四分位数に対して、iqrの1.5倍をひいたもののほうを、lower_rangeとします。

```
upper_range = iqr(latitude) * 1.5 + quartile(latitude, .75)
lower_range = quartile(latitude, .25) - iqr(latitude) * 1.5
```

Exploratoryを使ってひとつづつやっていきましょう。

###緯度のUpper Range を計算する

計算結果をわかりやすく見るために、テーブル画面に行ってください。

新しいステップを加えるために、＋ボタンをクリックしてください。そして、下記のように入力してください。

```
mutate(upper_range = IQR(latitude, na.rm=TRUE) * 1.5 + quantile(latitude, 0.75, na.rm=TRUE))
```

<img width="640" alt="mongo-upper-range.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/06200a32-e314-597b-406c-61b15df59080.png">


###緯度のLower Rangeを計算する

＋ボタンをクリックしてください。そして、下記のように入力してください。

```
mutate(lower_range = quantile(latitude, 0.25, na.rm=TRUE) - IQR(latitude, na.rm=TRUE) * 1.5)
```

<img width="1438" alt="mongo-lower-range.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/42f986fa-ef36-2dd0-c36c-27e1ec464545.png">


###緯度がupper rangeとlower rangeの間にあるか確認する

今なら、latitudeカラムがupper_rangeとlower_rangeの間にあるかを確認することができます。

＋ボタンをクリックしてください。そして、下記のように入力してください。


```
mutate(within_range = latitude < upper_range & latitude > lower_range)
```

lower_rangeとupper_rangeの間であるという条件を満たしているかどうかの結果がwithing_rangeという列にTRUEかFALSEとして入ります。

<img width="1439" alt="mongo-range-test.png" src="https://qiita-image-store.s3.amazonaws.com/0/91522/da32bae3-6880-aedd-e1af-76c1a73c05a1.png">


今なら、チャート画面に行って、色にこの新しいwithin_rangeカラムを指定することができます。そして、ニューヨークに向かってズームしてください。

![mongo-range2.png](https://qiita-image-store.s3.amazonaws.com/0/91522/2b00da81-dcdd-aa3d-da8f-045c0c965852.png)


ほとんどのレストランが、外れ値ではないけれども、まだいくつかは外れ値になっています。これは、閾値として指定した1.5倍という数字がきつすぎたからかもしれません。1.5ではなく3に更新することで、この外れ値を取り除くことができます。

更新するために前のステップに戻る前に、Pinボタンをクリックしてください。

![mongo-range7.png](https://qiita-image-store.s3.amazonaws.com/0/91522/9b952117-9e9b-6e6e-741f-4249739c72da.png)


Pinボタンをクリックをすると、あなたがどのステップをクリックしようと、Pinされたステップにチャートを固定することができます。

Pinされた今なら、私たちが、upper rangeとlower rangeを計算したステップに戻って、1.5から3に更新することができます。

![mongo-range14.png](https://qiita-image-store.s3.amazonaws.com/0/91522/4f6bd2ef-ea5f-1794-d659-12f8480e20a1.png)


ステップを更新するたびにRunボタンをクリックすることを忘れないで下さい。すると、マップをニューヨークにズームしたとき、このような感じになります。

![mongo-range12.png](https://qiita-image-store.s3.amazonaws.com/0/91522/9e3abf1e-1142-16b7-c97d-e28a0aa489bc.png)


今回は、ニューヨークの中の円がwithin_range列の範囲であることを示す青色になっていますね。

今回は、外れ値の閾値の設定がうまくいっているようですね。外れ値をフィルタリングするために新しいステップをこのように加えてください。

```
filter(within_range)
```

Runボタンを押して、Pinボタンを外すと、地図はこのような感じになります。

![mongo-range15.png](https://qiita-image-store.s3.amazonaws.com/0/91522/8fae6ad1-e3e8-78cb-ccd4-dece97fd400f.png)


まだ、ニューヨーク以外にもいくつかのデータが残っているかもしれません。また同じことを繰り返すこと、外れ値をもっと取り除くこともできます。

今回は、MongoDBのデータベースを使いましたが、MySQLのデータベースでもほぼ同じようなことができます。

##興味を持っていただいた方、実際に触ってみたい方へ

Exploratoryは[こちら](https://exploratory.io
)からβ版の登録ができます。こちらがinviteを完了すると、ダウンロードできるようになります。

チュートリアルは[こちら](http://docs.exploratory.io/tutorials/intro.html
)から見ることができます。

Exploratoryの日本ユーザー向けの[Facebookグループ](https://www.facebook.com/groups/1087437647994959/members/
)を作ったのでよろしかったらどうぞ

分析してほしいデータがある方や、データ分析のご依頼はhidetaka.koh@gmail.comまでどうぞ