Qlik SenseでR/Shinyを使う（実験段階）

[English version(with google translate) is here](https://translate.google.co.jp/translate?hl=ja&sl=ja&tl=en&u=http%3A%2F%2Fqiita.com%2Fsasanquaneuf%2Fitems%2Fcd4aefdd466c4c999d99)
# はじめに

この記事では、Qlik SenseとShiny(R)を組み合わせて使う具体的な実装を提案します。どちらも無料のツールです。
<img width="874" alt="qsload20.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/46a604b0-4bba-e1cc-1607-276c0a510bcb.png">

これによって、Qlik Senseでは、Rの持つ強力なパッケージ群の利用が容易になります。例えば機械学習、クラスタリング、統計処理、等が容易に行えるようになります。

逆にR(Shiny)の視点から見ると、Shinyの洗練されたUIに対して、さらにデータの抽出・加工の機能に特化したインターフェイスを付け加えることができます。例えば、あなたがお客様の購買動向に関する分析を行っているデータサイエンティストであったとすると、分析対象の顧客や、購買した物品に関する抽出の条件を「きわめてリズミカルに」変更して分析をすることが可能になります。
Shinyは非常に優れたインターフェイスを提供しますが、一般的なユーザに開放して、データの抽出観点を柔軟に変更させるためには、相当な作りこみが必要になります。また、ある程度のバリエーションを機械的に実行したり、逆に深い考察をしながら逐次対話的な分析はできますが、例えばテレビのチャンネルを切り替えるような感覚でデータの切り口を変更するには難があります。
一方のQlik Senseは、データの抽出観点を柔軟に変更するという点において非常に強力な一方で、単独では機械学習等の高度な操作を行うモジュール類を持ち合わせていません。
これらのツールの良いところを組み合わせてしまおう、というのが着想です。

現状、まだまだ粗削りな状態ではありますが、「こうやって組み合わせることができる」という方向性みたいなものを示すことができれば、と思っています。
今回のサンプルでは、Qlik Senseを用いて、
・有名な"Iris"のデータでクラスタリングをしてみます。
・Qlik Senseに標準で付属しているqvfを改造してアソシエーション・ルールを使って分析してみます。
スナップショットをいくつかつけているので、参考にしてください。なお、この例はほんの限られたものに過ぎず、ここで紹介しているQlik SenseのExtension、HelloShinyを使うことで、事実上任意のRコードが実行できるようになる、ということに注意してください。

# 環境構築
以下、Qlik SenseとShiny(R/RStudio含む)をインストールして、環境を構築します。
**【重要】**
・Qlik Sense Desktopを既にインストールしている場合は、エクステンションの配置のみ行ってください。
・Shinyを既にインストールしている場合は、ui.R/server.Rの配置のみ行ってください。また、Rが入っている場合、RStudioが入っている場合、等は、適宜その工程を省略します。

## Qlik Sense Desktopのセットアップ
Qlik Sense Desktopは無料でインストールすることができます。
### ダウンロード
http://global.qlik.com/jp/explore/products/sense/desktop
に必要な情報を入力し、ダウンロードします。64bitのWindows環境で動作します。
### インストール
ダウンロードしたプログラムを実行し、指示に従ってインストールします。
### エクステンションとqvfの配置★インストール済の場合も必須
以下のリンク先のRawをクリックすると、zipをダウンロードできるので、解凍します。
https://github.com/sasanquaneuf/HelloShiny/blob/master/Distribution/HelloShiny0.11_alpha.zip.zip
解凍すると、中にあるQlikSense\Extensionsフォルダの中身を、
`C:\Users\<ユーザ名>\Documents\Qlik\Sense\Extensions`
にコピーします。このエクステンションは、Qlik Senseの機能を拡張するようなJavaScriptのプログラムセットです。Shinyとの通信ができるように、独自の実装をしています。
また、同様にQlikSense\irisフォルダのiris.qvfとQlikSense\aruleフォルダのConsumer_Sales_Sample.qvfを
`C:\Users\<ユーザ名>\Documents\Qlik\Sense\Apps`
の中にコピーします。これはサンプルアプリです。irisはk-meansに、Consumer_Sales_Sampleはアソシエーション・ルールに、それぞれ使用します。

## Shinyのセットアップ
Shiny、および実行のために必要なR(および簡単に実行できるようにするためのRStudio)は無料でセットアップすることができます。
### Rのダウンロード・インストール
https://cran.ism.ac.jp/
の、Download R for Windows等のリンクをたどり、ファイルをダウンロードしてインストールします。
### RStudioのダウンロード・インストール
https://www.rstudio.com/products/rstudio/download/
の、RStudio 0.99.489 - Windows Vista/7/8/10等のリンクからファイルをダウンロードしてインストールします。
### Shinyのインストール（＋必要なパッケージのインストール）
RStudioを立ち上げ、次のコマンドを入力します。

```r
> install.packages("shiny")
> install.packages("stats")
> install.packages("stringr")
> install.packages("arules")
```

下の３つはshinyと直接関係ないですが、今回はk-meansによるクラスタリングのテストを簡単に試せるように、stats/stringrというパッケージもインストールします。また、アソシエーション・ルールを試せるように、arulesというパッケージもインストールします。

### ui.R/server.Rの配置
任意のフォルダを作り、先ほど解凍したファイルの中のShiny\kmeans_sample、Shiny\skelton_sample、Shiny\arule_sampleを適当な場所に配置します。これらのファイルは、Qlik Senseからのアクセスを受け付けるサーバプロセスの元になります。

### Shinyサーバプロセスの起動
Rstudioで、次のコマンドを実行します。

```r
> library(shiny)
> runApp(appDir="【kmeans_sampleを配置したパス(\は/に置換)/kmeans_sample】",port=7458,host="127.0.0.1")
```
例えば、`runApp(appDir="c:/test/kmeans_sample",port=7458,host="127.0.0.1")`というような具合です。

実行すると、RStudioのアイコンのブラウザが立ち上がり、ウィンドウが開きます。
このウィンドウは大切なウィンドウなので、大切に立ち上げたままの状態にしておきます（要するに閉じない。最小化OK。）。
<img width="446" alt="qsload14.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/132a111e-6daa-69c7-8184-7ba4e9f34c87.png">

# Irisにチャレンジ（k-means）
有名なIrisのデータで試してみます。
Qlik Senseを開くと、様々なアプリが表示されますが、先ほどのiris.qvfを開きます。

すると、右側にテキストボックスがあるので、Shinyを起動する際に出てきたウィンドウのURLをコピペして、startをクリックします。
<img width="284" alt="qsload16.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/1fa4b89e-ec12-d967-b2ec-1e702dabc65c.png">
※若干見た目が違っている可能性がありますが、Hello,Shinyの右のボックスに、Shinyで表示されたURLをコピペします。

雰囲気…
<img width="875" alt="qsload17.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/e0a6a169-98cd-2d33-584c-7cdb0acb72b7.png">
<img width="875" alt="qsload18.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/2f146837-03a9-3184-2394-28f05756742b.png">

# 仕組みの解説のための骨格標本
今回の仕組みに合わせて、Shiny側のプログラムを最低限の実装にしたスケルトンを用意しています。
このスケルトンも、上述の通りに適当なところに配置してshinyを起動します。

```r
> library(shiny)
> runApp(appDir="【skelton_sampleを配置したパス(\は/に置換)/skelton_sample】",port=7458,host="127.0.0.1")
```

このアプリにQlik Senseからアクセスすると、テーブルが表示されます。
<img width="875" alt="qsload19.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/d0c399c0-31cf-e6f4-dec8-4adc73fdf986.png">

# アソシエーション・ルール
今度は、Qlik Senseのサンプルとして付属しているqvfファイルを用いて、アソシエーション・ルールによるバスケット分析を試してみます。
RStudioのSTOPボタンを押すか、ブラウザの右上の×ボタンを押してkmeans用のプロセスを終了した後、上の場合と同様に、Rstudioで次のコマンドを実行します。

```r
> library(shiny)
> runApp(appDir="【arule_sampleを配置したパス(\は/に置換)/arule_sample】",port=7458,host="127.0.0.1")
```
<img width="471" alt="qss3.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/2e752eb4-636f-177c-df81-9396ea417e7a.png">
Qlik Senseを開き、**Consumer Goods Sales -add Shiny Sample -**アプリを選択します。
<img width="662" alt="qss4.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/a40ee60e-0d65-152d-b29c-6823cb14cbb6.png">
後は、画像の通りに操作します。
<img width="861" alt="qss5.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/86e9e4ad-3b79-3dd3-269a-a9f70347e06b.png">
<img width="862" alt="qss6.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/3afda802-b92d-ca4b-5c6c-7e720e5b2b36.png">
<img width="863" alt="qss7.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/ba913e07-7948-a073-be91-b98c76e3104f.png">
いわゆるバスケット分析です。この例では、一つの伝票に同時に含まれる商品の名前が分析の対象になっており、LHSの商品、例えばCRT-10670を含む場合、かなり高い確率でCR-10504も含まれることが分かります。
このようにして、実は意外な商品がセットで購入されている場合が発見されるかもしれません。
この分析の例として、しばしば目にするものに、ビールとおむつをセットで購入する客が一定数いる、という話があります。

# 同等のオブジェクトをQlik Sense上で作成する手順
ファイルを作って、データをロードし、オブジェクトを作る一連の手順をダイジェストでお送りします。Qlik Senseの操作に関しては、適宜マニュアルやQlikのコミュニティサイト等を参照してください。
<img width="493" alt="qsload1.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/53c9844b-9199-8989-aef5-33fd1b61f404.png">
<img width="491" alt="qsload3.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/583ab29b-cf67-6d9d-74b0-165a07401734.png">
<img width="364" alt="qsload4.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/67755ce2-54d4-c35e-453e-21789a78fc5b.png">
<img width="444" alt="qsload5.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/3a45f44e-6e4b-702b-ff6d-2495c008d3d4.png">
<img width="492" alt="qsload6.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/00923722-0292-352d-fc3d-f87dc77e6c92.png">
★ここでRowNo() as RowNum, というスクリプトを追加しておきます。
Qlik Senseの仕組み上、このRowNumが無いとデータがおかしくなる場合があります。
<img width="396" alt="qsload7.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/4f310fa4-f3db-58f3-b931-91684ab76c9f.png">
<img width="485" alt="qsload8.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/06eb0378-b6aa-7157-f679-f7d7881d8af1.png">
<img width="491" alt="qsload9.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/fe3f01c2-7ea9-0ef3-c09c-7f80f22d4f42.png">
<img width="375" alt="qsload10.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/b245bf14-0161-c6f7-1711-ba92a580c833.png">
★Hello Shinyをドラッグして、右側に適当にドロップします。
<img width="407" alt="qsload11.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/a954e4ff-bc5a-6680-a4c5-51e5bce675e6.png">
★「軸」を追加していきます。
<img width="391" alt="qsload12.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/f4d43ee7-aaf0-08ab-7381-1fa1414c4c75.png">
<img width="258" alt="qsload13.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/b117e0e6-8898-7ddd-4f1a-6b99978d90f5.png">
★Speciesはメジャーにしておきます。
<img width="446" alt="qsload14.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/d4c9a2ee-1eb6-3000-fd39-8f4e65975822.png">
<img width="284" alt="qsload16.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/a553ff62-7df9-4ea7-2adf-5c5e8b298834.png">
これで、冒頭のサンプルと同様の画面が得られます。
<img width="875" alt="qsload17.png" src="https://qiita-image-store.s3.amazonaws.com/0/94255/64f54936-37ac-12cf-b382-a0bf57eec7d1.png">

# 実際の可能性とか
とりあえずk-meansでやっていますが、実際、Rでできることはほぼすべて、なんでもできるはずです。Rで色々とデータの抽出条件を変えたりして検証したい仮説を、よりリズミカルに検証する環境づくり、という感じでとらえています。
簡単に試した限りですが、集計後データ件数4万件ぐらいだと、上記のスケルトンプログラムで普通にQlik Sense\<-\>Shinyやり取りができました。（明細は13万件程度）
明細が数百万、数千万の単位になったとき、きちんと動くかどうか、という部分は試していません。
データの規模がそれぐらい大きくなることを考慮すると、おそらく今のインターフェイス（Qlik Senseのデータを一括で渡す）よりは、ループ等によって分割しながらデータを登録して、最後のデータが登録された時点でShiny側で処理する、みたいな形にした方がよいかもしれません。
また、コピーペーストとはいえ、キーを入力しないといけない部分もちょっと遺憾なので、このあたりが改善すると非常に良いと思っています。
その他、結構適当な作り方なので、データには「,」が含まれてはいけないとか、色々微妙な制約はありますが、そうした課題を解決したソリューションが出てくると嬉しいなあ…と思っています。
その他の技術的な実装方法（リダイレクトして云々とか）については、[ShinyにQlik Senseからデータを渡す（プロトタイプ）](http://qiita.com/sasanquaneuf/items/0cb2619fbedc347f50f6)を参照してください。
全てのソースはhttps://github.com/sasanquaneuf/HelloShiny にあります。

# 余談
https://www.rstudio.com/faq-items/use-shiny-instead-tableau-spotfire-qlikview-similar-bi-tools/
http://www.piraeusconsulting.com/business-intelligence/r-and-shiny-the-cheat-sheet/

無料でここまでの環境を準備できるというのは、本当にいい時代になったものですね。
英語の翻訳ができたら、Qlik Communityにも投稿するかもしれません。