10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

コネヒトAdvent Calendar 2019

Day 24

Jupyter NotebookでKotlinが利用できるようになったので触ってみた

Last updated at Posted at 2019-12-24

本記事はコネヒト Advent Calendar 2019 24日目の記事になります。

はじめに

Jupyter Notebookはプログラムコードや数式、図、説明文などを含む文書を作成し、共有することが出来る、データ解析用のWebアプリケーションです。一見するとJupyter NotebookとKotlinはあまり関連性がなさそうに見えますが、Jupyter NotebookでもKotlinが使えるようになったので、触ってみた内容を共有したいと思います。

Jupyter NotebookでKotlinが利用できることを知った

KotlinConf 2019にて、Kotlin 1.4、Coroutines、Multiplatform、Spaceなど、Kotlinの最新情報からチーム開発を円滑に進めるためのツールまで様々なセッションがありました。たくさんのセッションがあった中にKotlinを用いたデータサイエンスに関連するセッションが3つありました。
スクリーンショット 2019-12-24 7.06.27.png
その中でもRoma BelovさんのセッションではKotlinを用いたデータサイエンスについて発表されて、主にツールやライブラリなどの側面からデータサイエンス に適用されるKotlinのエコシステムの説明がありました。また、Jupyter NotebookでKotlinが利用できる点にも触れています。

Jupyter NotebookでKotlinを利用するには?

Jupyter NotebookでKotlinを使うには、Kernelが必要になります。Kernelとは、入力されたコードをインタラクティブに処理して結果を返すプロセスのことを表します。すでに様々なKernelがあり、KotlinのKernelはkotlin-jupyter-kernelになります。Jupyter Notebook自体のインストール方法については割愛させていただきますが、kotlin-jupyter-kernelは、以下のようにCondaパッケージを使ってインストールします。kotlin-jupyter-kernelをインストール後にJupyter Notebookを起動し、「New -> Notebooks -> Kotlin」とKotlinのNotebookを作成できることがわかります。

$ conda install kotlin-jupyter-kernel -c jetbrains
$ jupyter notebook

スクリーンショット 2019-12-24 11.31.44.png

Notebookを新規作成して、Hello Worldを試した例です。また、ローカル環境だけでなくBinderというサービスからJupyter NotebookをWeb上で簡単に試すこともできます。

スクリーンショット 2019-12-24 11.39.22.png

データサイエンスのライブラリについて

ここまでJupyter NotebookでKotlinを使う部分について紹介しました。では、実際にデータ分析をするにはどうするのでしょうか。Kotlinには、以下のようにすでに多くのライブラリが存在します。下図の青い項目がKotlinのライブラリになります。

スクリーンショット 2019-12-24 7.07.24.png

lets-plotライブラリ

いくつかKotlinライブラリがあることがわかりましたが、ここからはlets-plotkranglのデータ操作とチャートに関するライブラリに絞って紹介したいと思います。まずはlets-plotで、これはチャートを簡単に描画できるライブラリです。具体的には以下のチャートがサポートされており、描画サンプルは以下の通りです。

チャート メソッド名
Area chart geom_area()
Bar chart geom_bar()
Boxplot chart geom_boxplot()
Contour chart geom_contour(), geom_contourf()
Density chart geom_density() and geom_density2d()
Error bar chart geom_errorbar()
Historgam geom_histogram()
Line chart geom_line()
Scatter chart geom_point()
Polygon chart geom_polygon()
Rectangle chart, Tile chart geom_rect(), geom_tile()
Image plot geom_image()

Boxplot chart

スクリーンショット 2019-12-24 12.03.33.png

Historgam chart

スクリーンショット 2019-12-24 12.18.08.png

Line chart

スクリーンショット 2019-12-24 12.31.16.png

Bar chart

スクリーンショット 2019-12-24 12.37.20.png

Scatter chart

スクリーンショット 2019-12-24 12.42.40.png

Tile chart

スクリーンショット 2019-12-24 12.47.03.png

Density chart

スクリーンショット 2019-12-24 12.53.07.png

kranglライブラリ

次にkranglライブラリについて説明します。データを行列のデータ形式に変換、集計、フィルタリングなど、データフレームの基本的な操作が行えます。kranglにはirisDataがバンドルされているのでそれらも用いてサンプルを作ってみます。

irisDataの表示

スクリーンショット 2019-12-24 13.05.38.png

データフレームの作成と表示

スクリーンショット 2019-12-24 13.16.24.png

Slackデータを用いたデータ分析

ここまで、Jupyter NotebookとKotlin Kernelとチャートとデータ操作ライブラリについて説明しました。では、Slackデータを用いて簡単なデータ分析をしてみましょう。Slackデータに関しては、権限があればワークスペースからデータを簡単にエクスポートできます。ワークスペースのデータをエクスポートすると、メッセージの履歴やファイルへのリンクにアクセスできる .zip ファイルをダウンロードできます。 データエクスポートには以下2種類あり、ワークスペースのオーナーと管理者によってのみ実行可能です。

公開データ ワークスペースの全データ
channels.json
dms.json
groups.json
integration_logs.json
mpims.json
users.json
全チャンネルのフォルダ

いくつかサンプルを紹介しますが、コネヒトのSlackデータを用いてデータ抽出を行いましたので、一部モザイクをかけています。

channels.jsonから参加者の多い上位のチャンネルを抽出する

// krangl, lets-plotのインポート
%use krangl, lets-plot

// Json配列からList型に変換
fun readFromJsonString(s: String) =
    s.removePrefix("JsonArray(value=[")
    .removeSuffix("])")
    .split(",")
    .dropLastWhile { it.isEmpty() }
    .toList()

// データフレームの生成
val channels = DataFrame.fromJson("channels.json")
    .addColumn("channle_members") { it["members"].map<String> { value -> readFromJsonString(value) } }
    .addColumn("count") { it["channle_members"].map<List<String>> { it.count() } }
    .filter { it["is_archived"] eq false }
    .select("id", "name", "channle_members", "count")
    .sortedByDescending("count")

// 出力用にデータの整形
val data = mapOf(
    "name" to channels["name"].asStrings().toList(),
    "count" to channels["count"].asInts().toList()
)

// グラフの描画
lets_plot(data) + 
    geom_bar(stat = Stat.identity) {
        x = "name"
        y = "count"
    }

plots1.png

users.jsonからTimeZone別にユーザを抽出する

// krangl, lets-plotのインポート
%use krangl, lets-plot

// データフレームの生成
val channels = DataFrame.fromJson("users.json")
    .filterByRow { (it["tz"] as? String)?.isNotEmpty() == true }
    .filterByRow { (it["deleted"] as Boolean) == false }
    .select("id", "name", "tz")
    .sortedByDescending("id")

// tz毎にグルーピング
val groupData = channels.groupBy("tz").count()

// 出力用にデータの整形
val data = mapOf(
    "name" to groupData["tz"].asStrings().toList(),
    "count" to groupData["n"].asInts().toList()
)

// グラフの描画
lets_plot(data) + 
    geom_bar(stat = Stat.identity) {
        x = "name"
        y = "count"
    }

スクリーンショット 2019-12-23 18.32.44.png

integration_logs.jsonからSlackのインテグレーションタイプ別に抽出する

// krangl, lets-plotのインポート
%use krangl, lets-plot

// データフレームの生成
val channels = DataFrame.fromJson("integration_logs.json")
    .filterByRow { (it["service_type"] as? String)?.isNotEmpty() == true }
    .select("service_type")

// service_type毎にグルーピング
val groupData = channels.groupBy("service_type").count()

// 出力用にデータの整形
val data = mapOf(
    "name" to groupData["service_type"].asStrings().toList(),
    "count" to groupData["n"].asInts().toList()
)

// グラフの描画
lets_plot(data) + 
    geom_bar(stat = Stat.identity) {
        x = "name"
        y = "count"
    }

plots2.png

最後に

KotlinでJupyter Notebookを触ってみました。KotlinはAndroidやサーバサイドで利用されている事例は増えていますが、データサイエンスの事例がとても少なかったので興味深かったです。すでに多くのライブラリが開発されており、何かしらコミュニティに貢献できればと考えています。

PR

コネヒトではエンジニアを募集しています!家族向けサービスをつくりたいエンジニアの皆さん、お待ちしています。
Connehito Image
家族の課題を解決するサービスのMAUを増やすAndroidエンジニア募集!

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?