LoginSignup
12

More than 5 years have passed since last update.

Matplotlibでリテンション率グラフを描画する

Posted at

モバイルアプリケーションの運営に欠かせない指標の1つであるユーザーリテンション、PartyTrack等の分析サービスを使っていると良く目にすると思う。ただ、自分の持っているデータでグラフを描画したいがWebフロントのJavaScriptは書きたくないというケースもある。

そんな時に見た次のエントリ

Making Pinterest — How Pinterest drives sustainable growth
http://engineering.pinterest.com/post/86533331849/how-pinterest-drives-sustainable-growth

コホートヒートマップが何かで描画されてる!! という訳で同じ見た目のグラフをPythonで描画してみる。

リテンション率のデータ

「ある日xに獲得したユーザーのy日後のアクティブ率z」を次の形で持っているとする。

{
    "2014/08/16": [翌日の値],
    "2014/08/15": [翌日の値, 2日後の値],
    "2014/08/14": [翌日の値, 2日後の値, 3日後の値],
    "2014/08/13": [翌日の値, 2日後の値, 3日後の値, 4日後の値],
    ...
}

グラフの描画

等高線をプロットするのと同じ要領でまずは獲得日x, 経過日数yのメッシュを作る。

from datetime import datetime
from matplotlib import dates
import numpy as np

vals = [
    datetime(2014, 8, 16), [0.524],
    datetime(2014, 8, 15), [0.574, 0.415],
    datetime(2014, 8, 14), [0.559, 0.440, 0.355],
    #略
]

# 表示する経過日数
max_y = 35

# xはdatetimeからnumberに変換しておく
x = map(lambda v: dates.date2num(v['date']), vals)
# yは1(翌日)からスタート
y = np.arange(1, max_y + 1)
# xとyのメッシュを作成
Y, X = np.meshgrid(y, x)

リテンション率の値がzとなるので、グリッドのyに配列の長さをあわせる。

def expand_z(v):
    v = v['values']
    v += list(np.zeros(max_y - len(v)))
    return v
# 縦横を揃えるためにゼロ埋め配列を追加する
z = map(expand_z, vals)
# numpyの行列に変換する
Z = np.array(z).reshape(len(z), len(z[0]))

pcolorを使って疑似カラープロットを描画する。

import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter

fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 4))

# プロットの作成
# データによって色が変わってしまうのを回避するため、最大値を指定
im = ax.pcolor(X, Y, Z, vmax=0.6)

# タイトル
ax.set_title(u'Launch Retention')
# y軸
ax.set_ylabel(u'Past Days')
ax.set_ylim(bottom=1)
# x軸
ax.set_xlim(x[0], x[-1])
# カラーバー
plt.colorbar(im)

# Ticks
minorLocator = MultipleLocator(5)
ax.xaxis.set_minor_locator(dates.DayLocator())
ax.xaxis.set_minor_formatter(dates.DateFormatter('%d'))
ax.xaxis.set_major_locator(dates.MonthLocator())
ax.xaxis.set_major_formatter(dates.DateFormatter('%Y %b'))
ax.xaxis.set_tick_params(which='major', pad=17)
plt.xticks(rotation=0)
plt.show()

結果

plot.png

できた。全体感を眺める用途には使えるだろう。?日後リテンションを指標として追うという場合は、別途その値だけ折れ線グラフか何かにすると経過を観察しやすい。どちらにしても、夜間バッチ処理で画像ファイルにしておけば、どこでも使えて便利。

今回のコードを手元で実行できる様にgistも用意しました、手元で動かしたい場合はこちらをどうぞ。
https://gist.github.com/hagino3000/455a68a79173fff1d890

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
12