Alteryxでカーネル密度推定してグラフを書いてみよう

こんにちは、小澤です。

先日Developers.IOにてExcel曲芸を披露しましたが、その中で「カーネル密度推定をする」というのがありました。 ところで、私はAlteryxと機械学習の人なのですが、あの発表以来どうにも"Excelの人"と思われている節があります。

そんなわけで、あの発表のあの分析をAlteryxでやるとどうなるの? という感じの話をしたいと思います。

カーネル密度推定をAlteryxでやってみよう

とはいえ、実はあの発表中のほとんどの機能に関してはすでにAlteryxで実現する方法を記述したブログ記事が存在しています。

さて、ここで出てきていないのがカーネル密度推定です。 Violin Plotで同様の結果が得られるのですが、AlteryxのViolin Plotツールは少々バンド幅が大きく変更もできないため、今回の目的ではちょっと使いづらくもあります。

そこで、ワークフローを作ってみようとなるわけです。

まずは愚直に計算する

とはいえ、Alteryxにはカーネル密度推定をする単一のツールはありません。 なので、実装します。

ワークフロー全体は以下のようになります。

流れとしては、

  1. 横軸となる値を生成
  2. カーネル関数の中身を計算
  3. 外側を計算してい特定のf(x)の時の値を求める
  4. グラフ化する

となります。

上側のGenerate Rowツールでは1の処理を行っています。 今回の設定では、0から60までの範囲を0.1刻みで作成していますが、実際のデータでは取りうる値の範囲で調整してください。 データの最大値・最小値を含む範囲として、刻みは幅は折れ線グラフがカクカクしてないように見える感じで刻んでおけばいいでしょう。

その下の部分では、ファイルからデータを読み込んだのち、Selectツールでカーネル密度推定の計算対象とする列のみに絞り込んでいます。 このSelectツールは必須ではありませんが、Append Fieldsツールが待ち構えているため、可能な限り不要なものは削除しておきます。

ここから計算していきます。 カーネル密度推定では、Generate Rowツールで作成した各値に対して、以下の計算を行います。

\[ \hat{f}(x)=\frac{1}{nh}\sum_i^nK(\frac{x-x_i}{h}) \]

hはバンド幅と呼ばれる別途設定するパラメータ、xはGenereta Rowツールで生成した各値、x_iはデータに含まれる各値です。

また、Kはカーネル関数と呼ばれるもので、この関数を変えることで柔軟な計算が可能となるのがカーネル密度推定の特徴です。 今回は一般的によく使われる以下のガウス関数を利用します。

\[ K(x) = \frac{1}{\sqrt{2\pi}}\exp(-\frac{x^2}{2}) \]

Ganerate Rowツールで生成された特定のxに対して計算をするには

  • 観測された各データx_iとGenerate Rowツールxに対してカーネル関数の計算を行う
  • それらを足し合わせてカーネル密度推定を行う

という計算を行う必要がありますので、推定するすべてのxに対して計算するにはAppend Fieldsツールで全組合せを求める必要があるというわけです。

さて、ではまずカーネル関数の中身を計算しましょう。 Formulaツールで以下のように式をそのまま入れるだけです。

ここでは、hの値はAlteryxのユーザ定数として定義したものを利用しています。

続いて、これをxの値ごとに足し合わせます。 これは、Summarizeツールで簡単に計算できます。

あとは、Formulaツールを使ってnhで割れば欲しい値が求まります。 nはデータ件数なので、あらかじめCount Recordsツールで計算したものをAppend Fieldsツールで付与しています。

最後にこのデータでグラフを作成します。 TypeをLineにして、横軸をGenerate Rowツールで作成した値、縦軸を計算した値にすることで、以下のようなグラフが生成されます。

Rツールを使う

さて、頑張って計算することでグラフ出力までできました。 しかし、Append Fieldsツールを使っているため、データ件数が多いとどうしても処理が重くなってしまいます。

そこで、Rツールを使った実装もしてみましょう。 こちらは非常に簡単です。

データをRツールの入力として与えて以下の処理をするだけです。

library(ggplot2)
df <- read.Alteryx2("#1")
g <- ggplot(df, aes(x=medv)) +
  geom_density(bw=%User.h%) +
  theme_bw()
AlteryxGraph2(g, 1)

「%User.h%」で先ほどと同様、ユーザ定義定数から値を取得しています。 以下のようなグラフが「1」から出力されます。

先ほどと形が一致してるのが確認できます。

せっかくなのでマクロにする

Rツールを使うと非常に簡単にカーネル密度推定できることがわかりましたが、「Rツール怖い」という方も中にはいるでしょう。 そんな時はマクロ化してしまえば、あとは内部でRツール使ってるなんて意識せずに使えます。

マクロの中身はこんな感じです。

普段からマクロを作ってる人だと、「なんかアンバランスだなぁ」と感じるかもしれません。 インターフェースに繋がってるのが上側だけで下からは何も生えてないからですね。 インターフェースの値をRツールから取得する際は、このように接続する必要がないんですね。

さて、簡単なマクロではありますが、中身を確認していきましょう。

まずはDrop Downツールです。 こちらは、列情報を入力のメタデータから取得して、選択対象を数値の列に絞っているだけです。 また、AnnotationでNameを「target」としています。

あとは、これをRツールから利用するのみです。

library(ggplot2)

df <- read.Alteryx2("#1")
AlteryxGraph2(
  ggplot(df, aes(x=%Question.target%)) +
    geom_density() +
    theme_bw()
, 1)

変わった点は、aesのxの引数を決め打ちしていたものをDrop Downで選択したものに置き換えた点のみです。

これで、マクロ化して任意のデータでカーネル密度推定ができるようになりました。

おわりに

今回は、Alteryxでカーネル密度推定をしました。

Alteryxはツール単体ではできなくてもいい感じに組み合わせれば色々実現できるのはもちろんですが、マクロ化することで共通処理を使いまわせるのも便利な点ですね。

Alteryxの導入なら、クラスメソッドにおまかせください

日本初のAlteryxビジネスパートナーであるクラスメソッドが、Alteryxの導入から活用方法までサポートします。14日間の無料トライアルも実施中ですので、お気軽にご相談ください。

alteryx_960x400