だいたいゼロから始めるApache Zeppelin(Sparkインタープリタ編)

## シリーズのリンク

1. [機能紹介編](https://qiita.com/muterion111/items/d141557e8c551c556de6 "だいたいゼロから始めるApache Zeppelin(機能紹介編)")(一度はお読みください)
1. [インストール・起動・停止編](https://qiita.com/muterion111/items/4caf9c227fac12c1560c "だいたいゼロから始めるApache Zeppelin(インストール・起動・停止編)")
1. [設定編](https://qiita.com/muterion111/items/c6547b444bbbac6c4737 "だいたいゼロから始めるApache Zeppelin(設定編)")
1. Sparkインタープリタ編
1. [その他インタープリタ編](http://qiita.com "だいたいゼロから始めるApache Zeppelin(その他インタープリタ編用)")(予定)

## 要約
- SparkインタープリタではSparkとSpark SQLを実行できる。
- 結果出力方法としてテーブル/棒グラフ/円グラフ/  
  面グラフ/折れ線グラフ/散布図を選択できる。

## Sparkインタープリタ設定
Sparkインタープリタ関連の設定方法には環境変数によるものと
プロパティによるものの２通りあります。
またSparkインタープリタでさせる処理が
依存するライブラリに対する独自の設定方法があります。
それぞれについて説明していきます。

### 環境変数による設定
Sparkをクラスタ上で実行する際には
環境変数`HADOOP_CONF_DIR`と
`SPARK_HOME`の設定が必須になります。

Apache ZeppelinにおけるSparkに関する環境変数は
下記のように`conf/zeppelin-env.sh`内にある
コメント`Use provided spark installation`以下の
各環境変数に付けられたコメントアウトを外しつつ値を設定します。

設定できる環境変数は大体が`spark-env.sh`に則ったものですが、
Apache Zeppelin独自のものもあります。

環境変数`MASTER`には以下の対応表に
則った設定値を指定することにより
対応するSparkの動作モードにできます。
また環境変数`SPARK_SUBMIT_OPTIONS`は文字通り
コマンド`spark-submit`のオプションとして渡されます。

|入力値|動作モード|  
|:-:|:-:|  
|local[*]|ローカルモード|  
|spark://(ホストアドレス):(ポート)|スタンドアローンモード|  
|yarn|Yarnモード|  
|mesos://(ホストアドレス):(ポート)|Mesosモード|  

yarnモードの場合にはインタープリタ設定画面で
Sparkのプロパティに`spark.submit.deployMode`を追加し、
以下のデプロイモードのいずれかを指定する必要があります。

|プロパティ`spark.submit.deployMode`に入力する値|デプロイモード|  
|:-:|:-:|  
|client|クライアントモード|  
|cluster|クラスタモード|  

```sh:conf/zeppelin-env.sh
# 設定前
# export MASTER=                                # Spark master url. eg. spark://master_addr:7077. Leave empty if you want to use local mode.
(中略)
## Use provided spark installation ##
## defining SPARK_HOME makes Zeppelin run spark interpreter process using spark-submit
##
# export SPARK_HOME                             # (required) When it is defined, load it instead of Zeppelin embedded Spark libraries
# export SPARK_SUBMIT_OPTIONS                   # (optional) extra options to pass to spark submit. eg) "--driver-memory 512M --executor-memory 1G".
# export SPARK_APP_NAME                         # (optional) The name of spark application.
(中略)
# Options read in YARN client mode
# export HADOOP_CONF_DIR                        # yarn-site.xml is located in configuration directory in HADOOP_CONF_DIR.

# 設定後
export MASTER=(Sparkの動作モードに対応する設定値)                                # Spark master url. eg. spark://master_addr:7077. Leave empty if you want to use local mode.
(中略)
## Use provided spark installation ##
## defining SPARK_HOME makes Zeppelin run spark interpreter process using spark-submit
##
export SPARK_HOME=(Sparkがインストールされたディレクトリのパス)                             # (required) When it is defined, load it instead of Zeppelin embedded Spark libraries
export SPARK_SUBMIT_OPTIONS="--driver-memory 1g --driver-cores 1 --executor-memory 4g --num-executors 2 --executor-cores 2 --supervise --conf \"spark.executor.extraJavaOptions=-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps\""                   # (optional) extra options to pass to spark submit. eg) "--driver-memory 512M --executor-memory 1G".
# export SPARK_APP_NAME                         # (optional) The name of spark application.
(中略)
# Options read in YARN client mode
export HADOOP_CONF_DIR=(Hadoopがインストールされたディレクトリにあるconfディレクトリへのパス)                        # yarn-site.xml is located in configuration directory in HADOOP_CONF_DIR.
```

### プロパティによる設定
Apache Zeppelinのインタープリタ設定画面にて
Sparkインタープリタの設定一覧にスクロールして
下記画像のプロパティ`master`の行のテキストボックスに
先述した対応表に則った設定値を入力することで
対応する動作モードを指定できます。

![Sparkインタープリタの設定一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/c2c56ad0-3ba6-5972-efdd-f13ba663f89c.png)

上記以外にも下記のようなプロパティを設定できます(一部抜粋)。

|プロパティ名|説明|デフォルト値|  
|:-:|:-:|:-:|  
|master|動作モード|local[*]|   
|spark.cores.max|Sparkの各種処理で使用するコア数(指定なしで使用可能な全コア数)||   
|spark.executor.memory|エグゼキュータで使用するメモリサイズ(例：512m,32g)|1g|   
|zeppelin.pyspark.python|ドライバープログラムとエグゼキュータ両方でpythonを呼び出す際のコマンド|python|   
|spark.executor.memory|エグゼキュータで使用するメモリサイズ(例：512m,32g)|1g|   
|zeppelin.spark.concurrentSQL|複数のSpark SQLを並列で実行させる場合はtrue|false|   
|zeppelin.spark.maxResult|Spark SQLの最大表示行数|1000|   
|zeppelin.spark.sql.interpolation|事前に`z.put("(変数名)",(値))`という処理で格納した値をSpark SQLに挿入できるようにする場合はtrue|false|   

### 依存ライブラリ設定
依存ライブラリの設定をするには[以前説明したインタープリタ設定](https://qiita.com/muterion111/items/c6547b444bbbac6c4737#%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%97%E3%83%AA%E3%82%BF%E8%A8%AD%E5%AE%9A)の
`Dependencies`で設定する方法や
Sparkの設定ファイル`${SPARK_HOME}/conf/spark-defaults.conf`で
各種設定をする以外にも、
先述した環境変数`SPARK_SUBMIT_OPTIONS`に対して
下記オプションを挿入することでもできます。

|挿入するオプション|オプション値|備考|  
|:-:|:-:|:-:|  
|--jars|JARファイルへのパスのカンマ区切りの文字列|JARファイルは実行環境内に存在しなければならない|   
|--packages|Mavenにおけるライブラリを指定する文字列`(groupId):(artifactId):(version)`のカンマ区切りの文字列|ライブラリはMavenによって解決される|   
|--files|ファイル(JARファイル以外も可)へのパスのカンマ区切りの文字列|エグゼキュータのノードのみ有効|   

## 実行例の説明に移る前に
以降実行例の説明に移るのですが
それらに使われるデータは[Quilt Data](https://open.quiltdata.com/)というサイトで
検索した公開データを使わせていただきました。
関係者各位にお礼を申し上ます。

## Spark実行
Sparkのコードを実行させるには
下記画面のようにノートブックのパラグラフの先頭行に
Sparkインタープリタを示す文字列`%spark`を指定します。
あとSparkのコードを書くだけですが、
[以前紹介したしたDynamic Form](https://qiita.com/muterion111/items/d141557e8c551c556de6#apache-zeppelin%E3%81%AE%E6%A9%9F%E8%83%BD%E4%B8%80%E9%83%A8%E6%8A%9C%E7%B2%8B)を挿入することもできます。
最後の行に`z.show((データフレーム or データセット))`という
メソッドを呼び出しています。
こうすることでApache Zeppelinの特徴であるリッチな結果出力が得られます。
![Spark実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/3b348d69-63da-4647-f072-26c38921d9ed.png)

結果出力方法は以下の種類があります。

- テーブル
- 棒グラフ
- 円グラフ
- 面グラフ
- 折れ線グラフ
- 散布図

なおこのような結果出力方法はSparkに限らず、
Spark SQL等の他データソースのインタープリタでも実現できます。
それぞれについて例示します。

### テーブル
上記でも示しましたが出力方法として
テーブルを選択すると下記画像のようになります。
テーブルの各列をクリックすると
トグルで昇順/降順を選択できるソート処理が実行されます。

さらに各列の右側にある下矢印のボタンをクリックすると
下記画像のようにメニューが表示され、
そのメニューの項目`Sort Ascending`/
`Sort Descending`を各列ごとに選択することにより
選択した複数列を組み合わせたソートが可能になります。

リンク`settings`をクリックすると下記画像のように
テーブル表示設定が選択できます。

選択できる項目は以下の通りです。
これらの項目のチェックボックスをチェックしたのち
ブラウザを再描画することで設定が初めて反映されます。

|設定名|設定内容|備考|  
|:-:|:-:|:-:|  
|useFilter|各列上部に入力値を含んでいる行のみを表示するフィルタを追加|-|   
|showPagination|テーブル下部にページャーを追加|-|   
|showAggregationFooter|テーブル下部に集計結果を表示(するらしい)|どうやっても表示されない・・・|   

![テーブル例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/605ac3d4-c509-9096-7d6d-48e2258e9c85.png)

### 棒グラフ
出力方法として棒グラフを選択すると下記画像のようになります。

リンク`settings`をクリックすると下記画像のように
上部に結果であるデータセット/データフレームを
構成するカラム名のラベルが表示され、
下部にそれらのドラッグ&ドロップ先となるテキストエリアを
入力領域とする各種設定が表示されます。

各種設定の内容は以下の通りです。

|設定名|設定内容|備考|  
|:-:|:-:|:-:|  
|keys|グラフのx軸を構成するカラム|複数カラム選択可|   
|groups|グラフ出力時の集計処理でグルーピング対象となるカラム|複数カラム選択可|   
|values|`keys`と`groups`のカラムのもと集計された結果がグラフのy軸を構成するカラムとその集計方法|複数カラム選択可|   

なお注意点として 
**`values`に選択されたカラムは必ず集計処理にかけられる** という点です。
つまり個々のレコードの値をグラフに
表示することは想定されていません。
この点はテーブル以外の他の結果出力方法でも
同様なのでご注意ください。

`values`でとりうる集計方法は以下の通りです。

- 合計(sum)  
- カウント(count)  
- 平均(avg)  
- 最小(min)  
- 最大(max)  

![棒グラフ例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/75b9b764-f432-0022-ee9c-38538fc6724b.png)

### 円グラフ
出力方法として円グラフを選択すると下記画像のようになります。

リンク`settings`をクリックすると棒グラフと同様の各種設定が表示されますが、
`keys`と`groups`のどちらにカラム名のラベルをドラッグ&ドロップしても
同様にグルーピングされます(円グラフ右上にあるグループのラベルの表示が変わるだけです)。

下記画像のように円グラフ上にマウスオーバーすると
グループのラベル名と集計値並びにグループのカウントの全体に占める割合が表示されます。

各種設定の内容は以下の通りです。

|設定名|設定内容|備考|  
|:-:|:-:|:-:|  
|keys|グラフ出力時の集計処理でグルーピング対象となるカラム|複数カラム選択可|   
|groups|グラフ出力時の集計処理でグルーピング対象となるカラム|複数カラム選択可|   
|values|`keys`と`groups`のカラムのもと集計された結果がグラフを構成するカラムとその集計方法|複数カラム選択可|   

`values`でとりうる集計方法は棒グラフと同じです。

![円グラフ例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/6555c990-3edd-85c1-fe44-2d8cfc634c21.png)

### 面グラフ
出力方法として面グラフを選択すると下記画像のようになります。

リンク`settings`をクリックすると棒グラフと同様の各種設定が表示され、
設定内容も同じものになります。

下記画像のように面グラフ上にマウスオーバーすると
その位置におけるx軸の値、各グループのラベル名と集計値が表示されます。

`values`でとりうる集計方法も棒グラフと同じです。

![面グラフ例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/29c1e254-8cda-9d5e-38ab-d7826aea29d2.png)

### 折れ線グラフ
出力方法として折れ線グラフを選択すると下記画像のようになります。

リンク`settings`をクリックすると棒グラフと同様の各種設定が表示され、
設定内容も同じものになります。

下記画像のように折れ線グラフ上にマウスオーバーすると
その位置におけるx軸の値、各グループのラベル名と集計値が表示されます。

`values`でとりうる集計方法も棒グラフと同じです。

このように折れ線グラフは棒グラフ/面グラフとほぼ同様の性質を持っていますが、
ズーム機能がある点が異なります。
下記画像の左側にあるチェックボックス`zoom`をチェックすると、
グラフの下に押し潰されたようなグラフが表示されます。
このグラフの両側にあるタブをドラッグしながら左右に動かすと
端からタブまでの領域が実物のグラフに **表示されなく** なります。
これにより上記領域以外がズームされて表示されるというわけです。

![折れ線グラフ例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/6b25db9e-51c3-a2f7-2e8c-2bfd76ad2ca7.png)

### 散布図
出力方法として散布図を選択すると下記画像のようになります。

リンク`settings`をクリックすると下記画像のように
他の結果出力方法とは異なる設定が表示されます。

各種設定の内容は以下の通りです。

|設定名|設定内容|備考|  
|:-:|:-:|:-:|  
|xAxis|グラフのx軸を構成するSpark実行時にグルーピングに用いたカラム|単一カラムのみ選択可|   
|yAxis|グラフのy軸を構成するSpark実行時にグルーピングに用いたカラム|単一カラムのみ選択可|   
|group|`xAxis`、`yAxis`のカラム以外でSpark実行時にグルーピングに用いたカラム|単一カラムのみ選択可|   
|size|Spark実行時に算出した集計結果である数値|単一カラムのみ選択可|   

下記画像のように散布図上にマウスオーバーすると
直近の点におけるx軸/y軸の値、グループのラベル名が表示されます。
`size`で指定した集計結果の値は点の大きさとして反映されます。

注意点としては **`xAxis`/`yAxis`に指定したカラムが取りうる値が
離散値でなければ`size`がグレーアウトされてカラム名を指定できない** 点です。
ここでいう`離散値`とは具体的には以下のものを指します。

- 文字列型のカラム値
- 他の点と重ならずに表示できる値の個数が全体の5%以上を占める数値型のカラム値
 
![散布図例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/32f8ae88-23fc-1735-480a-7f8f9d74b744.png)

## Spark SQL実行
Spark SQLの実行例の説明の前に下記画像のように
Spark実行例のものと同じ公開データを一時ビュー`trip_data`に格納します。
![一時ビュー作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/edca59a8-6b1b-382e-f02b-22a5155d4802.png)

あとは下記画面のようにノートブックのパラグラフの先頭行に
Spark SQLインタープリタを示す
文字列`%spark.sql`を指定してSpark SQLを記述します。
このときもマークダウンやSQL向けのDynamic Formを挿入できます。
![Spark SQL実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556213/8b5c31e9-a8bd-5a54-4563-4f2ae695bdbf.png)

## つづき
次回は[その他インタープリタ編](http://qiita.com "だいたいゼロから始めるApache Zeppelin(その他インタープリタ編用)")(予定) です。