minne データ分析

minne のマーケティングダッシュボードを Redash に移行しました

minne データ分析

技術部の @gyugyu@zaimy です。

データ分析の必要性が叫ばれており、様々な分析手法やノウハウが広がっている昨今ですが、分析に際してはその前段階として、いかにデータを効率よく集め分析可能な状態に置くかということに関する課題解決、すなわちデータエンジニアリングも必要です。

今回、このデータエンジニアリングにおいて課題を抱えていた minne のマーケティングダッシュボードを Tableau ワークブックから Redash に移行したので、その対応の一部をご紹介します。

移行の背景

minne では BI ツールの Tableau を導入しており、分析担当者はワークブックの編集が可能な Tableau Desktop を、分析担当者以外のパートナー (ペパボでは一緒に働く仲間のことをパートナーと呼んでいます) はビューワである Tableau Reader を利用しています。マーケティングダッシュボードは Tableau ワークブックにより作成されており、分析担当者が Tableau Desktop で更新・配布することで運用されていました。

Tableau Desktop はデータ分析において非常に強力なツールですが、minne でダッシュボードとして運用されていたワークブックには以下の課題がありました。

  • ワークブックの分割ができておらず内容が肥大しているためデータ取得に時間が掛かる
    • データソースに接続するクエリ数が多い
    • 分析用のワークブックを転用したため非集計データを取得している
  • 多くのパートナーが必要とするダッシュボードを Tableau Deskotp のライセンスを持っている分析担当者しか更新することができない

これらの問題は Tableau ファミリーの中でダッシュボード用途に強い別製品を利用することでも解消できますが、minne では既に環境が構築されていた Redash への移行を行いました。

Redash とは

Redash は Web インターフェースでクエリの記述を行い、得られたデータを可視化できるツールです。
接続できるデータソースも多く、スケジューリング機能やキャッシュ機能など便利な機能が備わっています。
ホスティング版と OSS 版が提供されており、minne では OSS 版を利用しています。

データフローの整備

従来のデータフロー

これまでのダッシュボード更新に必要なデータのフローは以下のようなものでした。

image

Database and other icons by Icons8 / The R logo is © 2016 The R Foundation.

  1. R スクリプトが minne のデータベースへ集計クエリを発行する
  2. R スクリプトが集計結果を Gist に保存する
  3. R スクリプトが Gist の URL を Slack へ通知する
  4. 分析担当者が Gist を参照して集計結果を Google SpreadSheet へ記録する
  5. 分析担当者が BIツール (Tableau) を操作して Google SpreadSheet やその他の集計データ、または minne のデータベースから非集計データを取得してダッシュボードを更新する

このデータフローは建て増し的に構築されたため、ダッシュボードの更新までに Gist や Slack を経由していたり、分析担当者による作業が必要だったりと冗長になっていました。また Tableau ワークブック内部に定義されたクエリは分析担当者しか確認することができず、前処理を行うスクリプトも R によって記述されており、メンテナンス性も高いとは言えない状態でした。

移行後のデータフロー

移行後のデータフローは以下のようになっています。

image

  1. Ruby または R スクリプトが minne データベースへ集計クエリを発行する
  2. Ruby または R スクリプトが measurement データベース (ダッシュボード用の集計データベース) へ集計結果を保存する
  3. パートナーが Redash を参照すると measurement データベースとその他の集計値からデータが取得され可視化される

既存の R スクリプトの出力先を Gist から measurement データベースにすることで資産を活かしつつ、新規のスクリプトやリファクタリングしたスクリプトはペパボで広く利用されている Ruby へ移行しています。

従来のフローと比べて簡潔になり、一連の処理は人間の作業を必要とせず自動的に行われるようになりました。

集計データベースの構築

これまでのデータフローで使われていた Google SpreadSheet は、毎日分析用のデータが継ぎ足されていたために視認性が低く、Google SpreadSheet よりデータベースを使用する方が適切であると考えられました。そこで、ダッシュボード用に新たに measurement データベースを構築し、そちらへとデータを流し込むように変更しました。また、これまでの Google SpreadSheet は集計用の非正規化されたデータのみを保持していたのですが、データベースの構築を機にスキーマの見直しを行い、正規化されたデータを持つようにしました。

データベースへの移行により、本番用とは別に開発用のデータベースを用意する必要ができたので、開発環境と開発用・テスト用データベースを Dockerdocker-compose で構築しました。開発にあたってはデータベースへの操作が妥当であるかを確かめることが必須なので、新規開発のスクリプトは自動テストに基づいて開発されています。同様に、これまで建て増しされた R のスクリプトに対しても、正しく実行できるかを確かめるテストが Python で書かれており、安全性を担保しています。

前処理を行うスクリプトの管理

以前の R スクリプトは GitHub Enterprise で管理されていたものの、実行サーバへの配置は手作業のまま建て増しが行われ、リリース作業が複雑になっていました。これらをデプロイツールでサーバ上に配置するように変更し、コマンド一つで実行サーバへの配置が完了するようになりました。デプロイツールは社内でも採用実績のある Capistrano を用い、併せて Whenever を使うことで定時実行の定義も Git 上で管理できるようにしました。

スクリプトの管理においてもう一つ重要なことは、依存するライブラリの管理です。開発環境と本番環境で同じライブラリの同じバージョンがインストールされていることを保証するために、 Ruby スクリプトが依存する Gem の管理は Bundler で行います。同じように R スクリプトも依存ライブラリのインストールを行う必要があり、これには Packrat というパッケージ管理ツールを用いています。

Redash ダッシュボードでの工夫

Redash のダッシュボード機能は、個別のクエリ結果を可視化したものをウィジェットとして並べることができます。
素直にウィジェットを並べるだけでもダッシュボードを作ることができますが、いくつか工夫した点や Tips をご紹介します。

クエリのドリルダウン

以下のように a タグを返すようにすることでリンクを記述できます。
リンク先のクエリに URL パラメータで値を渡すこともできるため、サマリのクエリにリンクを埋め込んでおいて気になるデータがあれば個別にドリルダウンしたり実際のページを確認する、という使い方をしています。

-- キュレーションのサマリを表示する
SELECT
  curations.date
  , curations.title
  ...
  , CONCAT('<a href="/queries/245?p_id=', curations.id, '" target = "_blank">掲載前後の変化を見る</a>') AS 'link_to_chart'
  , CONCAT('<a href="https://minne.com/curations/', curations.id, '" target = "_blank">minneで見る</a>') AS 'link_to_curation'
FROM
  ...

キュレーションのサマリを表示 image

サマリの「掲載前後の変化を見る」リンクをクリックして個別のデータを表示 image

パラメータを一括指定する UI の追加

Redash では {{param}} のように注括弧で括った文字列をクエリ中に記述すると、その文字列をラベルに持つパラメータを利用できます。
パラメータの値は GUI 上でフォームに入力したり、URL パラメータで渡したりすることでクエリに埋め込めるため、開発者や分析担当者がクエリを記述してから他のパートナーに任意の値を入れてもらって実行するなどの使い方ができます。

パラメータはダッシュボード上でも指定できますが、クエリごとにフォームに値を入力していくのは大変です。
Redash のダッシュボードには JavaScript を記述できるため、以下のように URL パラメータを付けてダッシュボードを GET する UI を作成してパラメータを一括指定できるようにしています。

<div style="margin:20px">
  <form action="/dashboard/example" method="get">
    <p>
      開始日 <span style="margin-right:20px"><input type="text" name="p_from"></span></br>
      終了日 <span style="margin-right:20px"><input type="text" name="p_to"></span>
      <input type="hidden" name="maxAge" value="0">
      <input type="submit" value="実行" >
    </p>
  </form>
</div>
<script type="text/javascript">
  d_from = moment().startOf('year').format("YYYY-MM-DD");
  d_to = moment().endOf('year').format("YYYY-MM-DD");
  format = 'yy-mm-dd';
  $.datepicker.setDefaults($.datepicker.regional['ja']);
  $('input[name="p_from"]').attr('value', d_from).datepicker({
        dateFormat: format
    });
  $('input[name="p_to"]').attr('value', d_to).datepicker({
        dateFormat: format
    });
</script>
<link type="text/css" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/flick/jquery-ui.css" rel="stylesheet" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.js"></script>

パラメータを利用する場合のクエリ結果の更新

Redash ではクエリ結果がキャッシュされるため、再度クエリを開いた際もすぐに結果を参照できます。一方で最新の結果を得るにはクエリを再実行するかスケジューリング機能による自動実行を利用する必要がありますが、パラメータを利用しているクエリではスケジューリングでの実行時にパラメータのラベルが文字列として評価されてしまい、意図した結果を得られないという問題がありました。

今回はダッシュボード上で集計期間を指定できるようにパラメータを利用する必要がありましたが、クエリごとに再実行操作を行うのは手間なので、URL パラメータとして maxAge=0 をダッシュボードに渡すことでキャッシュを無効化して常に最新の結果を得られるようにしました。
ダッシュボードの読み込みごとにクエリが実行されるため、個々のクエリの実行に時間が掛かる場合には向きませんが、今回はデータフローの整備に伴ってクエリも軽量になったためこの方法を採用しています。

まとめ

minne では探索的な分析に引き続き Tableau Desktop を利用しつつダッシュボードを Redash に移行することで、分析担当者は柔軟な分析を行いつつチームのパートナーはいつでも最新の指標を参照できるようになりました。

これからも、必要なデータをより手軽に得られるようにすることで、チームが効果的な施策の企画や実施に注力できる環境を広げていきたいと考えています。

以上、minne のマーケティングダッシュボードを Redash に移行した話でした。

※本記事中の記述は Redash バージョン 0.12.0+b2449 の仕様に基いています。