遊覧飛行ーワインとゲームー

都内某所で働くゲームクリエイターのブログ。ゲームやビジネスに関する話題、シリアスゲームの紹介、作成したゲームの公開、ワインに関する記事など徒然なるままに書き記していきます。

スマホゲームの基本KPI -2. インストール数, NUU-

f:id:ngyope:20160417155010j:plain

スマホゲームの KPI に関する解説、第2回です。

今回はゲームを遊んでくれる「人」に注目した KPI、インストール数と NUU について解説していきます。

前回と同様、主な読者層としては、将来スマホゲームの業界で働きたいと思っている学生や、入社したてでこれから現場に入っていく新入社員の方などです。

 

基本 KPI 1. -インストール数-

大半のスマホゲームは App Store や Google Play Store などのプラットフォームにて公開されており、そこで日々人々によってインストールされています。

このインストールされた回数を示す指標が、その名の通りインストール数です。誰がインストールしたかを問わず、1回のインストールを1インストールとしてカウントしています。また、インストール数はあくまでインストールされた回数を純粋にカウントするため、同じ人が2回、3回…と複数回インストールした場合は、2回、3回と複数回カウントすることになります。

それゆえに、インスト―ル数は必ずしも新しく入ってきた人の人数を表すわけではなく、通常はその人数よりも大きな値となります。

 

基本 KPI 2. -NUU-

インストール数とは別に、やはりその日に入ってきてくれたユーザーが純粋に何人いたかを把握したいですし、する必要があります。それを示す指標が NUU (エヌユーユー: New Unique Users) です。

NUU はインストール数をもとにした値ですが、同じ人に2回、3回とインストールされた場合でも、新規流入顧客数を示す NUU は 1とカウントします。スマホゲームではチュートリアル後のガチャでいいものを狙ういわゆるリセマラが良く行わるため、新規流入顧客を把握するうえではインストール数よりもこの NUU がよく用いられます。*1

1日の利用者数を表す DAU を増やすためには、いかにしてより多くの NUU を獲得するかがキモとなります。NUU を増やすために、CMやネット広告などの広告を出す、ゲームの記事を出稿してもらう、口コミによる拡大を狙うといったマーケティング施策が主に用いられています。NUU はそのマーケティング施策がどれだけうまくいったかを表す指標としても用いられ、次の施策に生かされているのです。

また、蛇足ですが、NUUとインストール数を組み合わせることでリセマラ率という数字を出すこともできます。式としては NUU ÷ インストール数と単純なもので、インストール全体のうち何%がリセマラによるものなのかを示します。開いているガチャのキャラが強力なものだったりする場合、このリセマラ率は通常跳ね上がります。 

 

おわりに

今回は基本 KPI の中でも「人」の流入と関連の深いインストール数と NUU について見ていきました。プロダクトの拡大を図るにあたって、顧客数を増やすことは非常に重要なため、これらの KPI は DAU や ARPU などと同様に現場では日々欠かさず確認されている数字です。

また、ゲーム中の「人」に着目した重要な指標として、もう 1つ RR (リターンレート: Return Rate) というものがあります。本来ならばこの回で合わせて紹介するべきものですが、RR はゲーム特有の指標でかつ理解が少し難しいもののため、回を分けて解説することにします。 

 

バックナンバー

スマホゲームの基本KPI -1. DAU, PUU, ARPU, ARPPU, 課金率-

スマホゲームの基本KPI -2. インストール数, NUU-

スマホゲームの基本KPI -3. RR-

スマホゲームの基本KPI -4. RR変化率-

*1:ちなみに、会社によって違うかもしれませんが、同一の人による複数回のインストールを NUU = 1 としてカウントする方法として、同一人物による最終インストールにフラグを立てて区別し、それのみを NUU としてカウントするという方法が取られています。同一人物を判別する方法としては、iOS の IDFA や Android の AAID といったものが用いられています。

スマホゲームの基本KPI -1. DAU, PUU, ARPU, ARPPU, 課金率-

f:id:ngyope:20160417155010j:plain

このシリーズでは、スマホゲームのKPI (Key Performance Indicator: 重要業績評価指標) の基本に関して解説していきます。

主な読者層としては、将来スマホゲームの業界で働きたいと思っている学生や、入社したてでこれから現場に入っていく新入社員の方などです。

スマホゲームのKPIに関しては、すでに多くの記事もあるのでご存じの方も多数いらっしゃると思いますが、参考までにご覧ください。*1

スマホゲームのKGI -売上-

KPIの話に入る前に、似たようで別の指標である KGI (Key Goal Indicator: 重要目標達成指標) について軽く触れたいと思います。

KGI とはその名の通り「目標 = Goal」の達成を図る指標で、一番基本的なものとしては「売上」や「利益」があげられます。非営利として開発・運営するならまだしも、商品としてゲームを制作・運営するにあたっては「売上」は無視できない指標なため、売上がプロダクトの最終的な目標として設定されることが大半です。

そして、KPI は KGI を達成するためにその構成要素を分解し、最終目標がどれくらい達成できているか・できそうかを評価するために用いられます。

 

基本 KPI 1. -DAU, ARPU-

では、その「売上」はどのような KPI に分解可能なのでしょうか。

売上を分解する方法はいくつかありますが、最も基本的なものは売上を 顧客数 x 顧客単価 に分解する方法です。スマホゲームでは日次の KPI を追うことが多いため、顧客数は 1日の利用者数、顧客単価は 1日の利用者数の1人あたり売上を指します。前者を業界用語で DAU (ディーエーユー、ダウ: Daily Active Users)、後者を ARPU (エーアールピーユー、アープ: Average Revenue Per User) と呼びます。

日次売上 = DAU (1日の利用者数) x ARPU (1人あたり売上)

 ざっくり述べると、スマホゲームの運営にあたっては、この 2 つの KPI を最大化していくことで 売上の向上を図っていきます。

 

基本 KPI 2. -PUU, ARPPU- 

売上を分解するもう 1つの方法として、売上を課金者数 x 課金者1人あたりの顧客単価に分解するやり方があります。日次ではそれぞれ PUU (ピーユーユー: Paid User)、ARPPU (エーアールピーピーユー: Average Revenue Per Paid User) と呼びます。

日次売上 = PUU (課金者数) x ARPPU (課金者1人あたりの売上)

つまり、お金を払ってくれたユーザーの数と、その方々の平均課金額をかけた合わせることで、売上を出すことが可能というわけです。ダウンロード無料のゲームでは遊んでくれているユーザーを課金者/非課金者と分けられるため、こういった捉え方もあるわけなんです。

 

基本 KPI 3. -課金率-

これまで、DAU, ARPU, PUU, ARPPU と 4つの KPI を見てきました。最後に、これらと関係の深い「課金率」という KPI についてみていきたいと思います。

課金率とは、日次で考えるならば、1日の利用者数のうち何人の方に課金してもらえたかを表す指標です。

課金率 = PUU ÷ DAU

あくまで課金してくれた人数の割合を見るだけなので、課金者の課金額については何も語ってはいません。ですが、例えば 2つの日の課金状況について比較する際、実数値である PUU はそもそもの分母である DAU の大小の影響を受けてしまうため、その影響を除いた課金率で比較することも多く、ゲーム運営の現場ではよく使われる指標です。

 

おわりに

今回は最も基本的な KPI である 5つの KPI について見てきました。ゲーム運営の現場では日々これらの数字を追って現状を把握するとともに、これらの数値を基準に行った施策の振り返りをやっています。

もちろん、現場で使われている KPI はもっとたくさんありますが、ただ何でもかんでも数字を見ればいいのではなく、その数字が KGI にどうつながるのを意識し、その数字がどう変化すればどういうことが言えるのかを意識しつつ、運営を行っていくことが重要です。

 

バックナンバー

スマホゲームの基本KPI -1. DAU, PUU, ARPU, ARPPU, 課金率-

スマホゲームの基本KPI -2. インストール数, NUU-

スマホゲームの基本KPI -3. RR

スマホゲームの基本KPI -4. RR変化率-

*1:本シリーズではダウンロード無料、アイテム課金制のゲームを対象にして話を進めていきます。

SQLを学ぶ上で参考になったものまとめ

自分が SQL を勉強する上で約に立ったサービスや本を紹介します。

業務上 SQL を使うことが多いのですが、基本的なスキルは以下からちゃんと吸収すればしっかり身に着けることができるので、ぜひ参考にしてみてください。

 

ネット情報

まずは ドットインストール

まずはおなじみのドットインストール。
動画を使って、楽しく基礎の基礎を学ぶことができるため、最初のとっかかりとしてはすごくオススメです。

MySQLとPostgreSQLのほかに、SQLiteなんかもあった気がします。

 

MySQL初心者講座

ドットインストールの次に、復習もかねてこのサイトで勉強すれば、さらに基礎の定着が図れること間違いなし!

mysqlweb.net

 

練習問題

練習問題としては、このサイトに掲載されている問題を解きまくれば、さらに腕を磨くことができるでしょう。

テーブルの結合を結構使うことになるので、それまわりの練習にも最適です。

 

書籍

脱初級テキスト

とりあえずネットで基礎を学んだうえで、このテキストの内容を読み進めていくと飛躍的に実力が向上するでしょう。

実際の業務でも使用するようなテクニックはもちろん、DBに関する理論的な話や深い裏話なんかも載っているため、単純に読み物としても学ぶところが多いです。

なるべく標準SQLを使おうというスタイルのため、特定の方言に偏った内容ではありません。

達人に学ぶ SQL徹底指南書 (CodeZine BOOKS)

達人に学ぶ SQL徹底指南書 (CodeZine BOOKS)

 

 

分析系

分析系で参考にするならこのテキストかと。

PostgreSQLを使用した本で、特に WIndow関数あたりは分析を行っていくうえで自由自在に使えるようになったおく必要があります。

現場でも使えるような分析系の集計が主なため、これから分析に挑戦してみようという方は必見ですね。

10年戦えるデータ分析入門 SQLを武器にデータ活用時代を生き抜く (Informatics &IDEA)

10年戦えるデータ分析入門 SQLを武器にデータ活用時代を生き抜く (Informatics &IDEA)

 

 

その他オススメ記事 

yuranhiko.hatenablog.com

yuranhiko.hatenablog.com

yuranhiko.hatenablog.com

yuranhiko.hatenablog.com

MySQLメモーDAU、課金UU、課金率の集計ー

MySQLを使ってDAU、課金UU、課金率を表示する方法のメモ。

 

使用するテーブル

サンプル用の仮テーブルとして、以下のようなものを想定します。

access_log

f:id:ngyope:20160908231832j:plain

  • d:アクセスした日時
  • access_time:アクセスした時間
  • uid:アクセスしたユーザーのID

 

spend_money_log

f:id:ngyope:20160908231834j:plain

  • d:課金した日時
  • t:課金した時間
  • uid:課金したユーザーのID
  • amount:課金額

 

DAU、課金UU、課金率の集計

MySQLのクエリ

SELECT
accesst.d AS date,
COUNT(DISTINCT accesst.uid) AS dau,
COUNT(DISTINCT moneyt.uid) AS puu,
ROUND(COUNT(DISTINCT moneyt.uid)
/ COUNT(DISTINCT accesst.uid), 2) AS p_rate
FROM
access_log accesst
LEFT OUTER JOIN
spend_money_log moneyt
ON
accesst.d = moneyt.d
GROUP BY
date
ORDER BY
date
;

 

  • まず、access_log と spend_money_log を d(日時)で join
  • DAU:access_log から、日別に DISTINCT で uid を集計
  • 課金UU:spend_money_log から、日別に DISTINCT で uid を集計
  • 課金率:課金UU ÷ DAU

 

集計結果

f:id:ngyope:20160908233542j:plain

R の caret パッケージメモ~train:caret 決定木~

R で "caret" パッケージを使用する際の備忘録です。
今回は "train関数" を使用して決定木の構築を行います。

 

使用するデータ

使用するデータは一般化線形モデルの際にも使用した "Titanic" です。
沈没したタイタニック号の生存者数を「性別」「年齢」「等級」ごとに分類したデータです。

 

データの下準備

データの下準備は、一般化線形モデルを構築した際と同じです。

テーブルを変換する "expand.table関数" を使用しています。

> install.packages("caret")
> library(caret)
> install.packages("epitools") #テーブル変換関数のパッケージ
> library(epitools)

> Titanic1 <- expand.table(Titanic) #テーブル変換
> head(Titanic1)
Class Sex Age Survived
1 1st Male Child Yes
2 1st Male Child Yes
3 1st Male Child Yes
4 1st Male Child Yes
5 1st Male Child Yes
6 1st Male Adult No

 

train関数で rpart を実行

決定木を構築するアルゴリズムには CHAID, C4.5 / C5.0 / See5, CART など様々ありますが、ここでは CART を採用します。
CART で決定木を構築するメソッドは "rpart" です。

> titanic.rp <- train(
data = Titanic1,
Survived ~ Sex + Age + Class,
method = "rpart",)
<以下省略>

 

"rpart" では木の複雑度である "cp" をもとに木をコントロールすることができます。
"train関数" を使った場合は Accuracy に基づいて最も適切な cp を探索し、その最適値で最終的なモデルを出力します。

> titanic.rp
CART

2201 samples
3 predictor
2 classes: 'No', 'Yes'

No pre-processing
Resampling: Bootstrapped (25 reps)
Summary of sample sizes: 2201, 2201, 2201, 2201, 2201, 2201, ...
Resampling results across tuning parameters:

cp Accuracy Kappa
0.01125176 0.7822764 0.4195169
0.02250352 0.7769538 0.4161458
0.30661041 0.7189166 0.1863290

Accuracy was used to select the optimal model using the largest value.
The final value used for the model was cp = 0.01125176.
data = Titanic1,
Survived ~ Sex + Age + Class,
method = "rpart",)

 

 "summary関数" を用いれば、モデルに関して様々な情報を確認することができます。

> summary(titanic.rp)
<以下省略>

 

決定木のプロット

最終的な木のモデルは x$finalModel に格納されています。
ここでは "fancyRpartPlot関数" を用いて木のプロットを行います。

> library(rattle)
> fancyRpartPlot(titanic.rp$finalModel)

 

f:id:ngyope:20160830124513j:plain

R の caret パッケージメモ~train:caret 一般化線形モデル~

R で "caret" パッケージを使用する際の備忘録です。
今回は "train関数" を使用して一般化線形モデルで回帰分析を行います。

 

使用するデータ

使用するデータは "Titanic" です。
沈没したタイタニック号の生存者数を「性別」「年齢」「等級」ごとに分類したデータです。

 

データの下準備

いつも通り、"caret" パッケージをライブラリ化します。

また、"Titanic" のデータはそのままでは使いづらいため、テーブル変換用の関数を使って使いやすい形に変換します。

> install.packages("caret")
> library(caret)
> install.packages("epitools") #テーブル変換関数のパッケージ
> library(epitools)

> Titanic1 <- expand.table(Titanic) #テーブル変換
> head(Titanic1)
Class Sex Age Survived
1 1st Male Child Yes
2 1st Male Child Yes
3 1st Male Child Yes
4 1st Male Child Yes
5 1st Male Child Yes
6 1st Male Adult No

 

train関数でglmを実行

一般化線形モデルを指定するメソッドは "glm" です。
一般化線形モデルはパラメータ調整が必要ないため、コードは以下の通りとなります。
ロジスティック回帰分析を行うため、family は「二項分布 "binomial()"」を指定します。

titanic.glm <- train(
data = Titanic1,
Survived ~ Sex + Age + Class,
method = "glm",
family = binomial())
<以下省略>

 

Accuracy は約78%ということでボチボチかなと思います。

> titanic.glm
Generalized Linear Model
2201 samples
3 predictor
2 classes: 'No', 'Yes'
No pre-processing
Resampling: Bootstrapped (25 reps)
Summary of sample sizes: 2201, 2201, 2201, 2201, 2201, 2201, ...
Resampling results:
Accuracy Kappa
0.7772942 0.4447814

 

summary関数を使ったあとは、普通の glm関数と同じですね。

> summary(titanic.glm)
Call:
NULL
Deviance Residuals: 
Min 1Q Median 3Q Max 
-2.0812 -0.7149 -0.6656 0.6858 2.1278
Coefficients:
Estimate Std. Error z value Pr(>|z|) 
(Intercept) 0.6853 0.2730 2.510 0.0121 * 
SexFemale 2.4201 0.1404 17.236 < 2e-16 ***
AgeAdult -1.0615 0.2440 -4.350 1.36e-05 ***
Class2nd -1.0181 0.1960 -5.194 2.05e-07 ***
Class3rd -1.7778 0.1716 -10.362 < 2e-16 ***
ClassCrew -0.8577 0.1573 -5.451 5.00e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2769.5 on 2200 degrees of freedom
Residual deviance: 2210.1 on 2195 degrees of freedom
AIC: 2222.1
Number of Fisher Scoring iterations: 4

 

メソッドで "glmStepAIC" を選択する

メソッドで "glmStepAIC" を選択すると、AIC (赤池情報量規準) に基づいて変数選択を行い、最適なモデルを構築してくれるので便利です。

titanic.glm <- train(
data = Titanic1,
Survived ~ Sex + Age + Class,
method = "glmStepAIC", #AICに基づきモデル構築
family = binomial())
<以下省略>

R の caret パッケージメモ~train:caret 線形回帰~

R で "caret" パッケージを使い始めたので、その備忘録です。
まずは、線形回帰分析 (lm) の仕方をメモ。

 

最初に、"caret" パッケージをインストール。
"caret" をライブラリ化すると、合わせて "lattice", "ggplot2" もロードされます。 

> install.pachages("caret")

> library(caret)

  

今回は、車が停滞するまでに必要な距離(速度別)のデータである "cars" を使用します。
※余談ですが、このデータは 1920年代に測定されたものだそうです。

> dim(cars)
[1] 50 2


> head(cars)
   speed  dist
1        4      2
2        4    10
3        7      4
4        7    22
5        8    16
6        9    10

 

 

モデル構築を行うには "train関数" を使用します。

> cars.lm <- train(

 + data = cars,        # 元となるデータを選択

 + dist ~ .,               # 結果変数と説明変数を選択

 + method = "lm")   # モデル選択。線形回帰は "lm"

  

モデルの評価は "RMSE" の値を確認します。
この値が小さいほど、モデルの性能がいいことを示します。

> cars.lm
Linear Regression

50 samples
1 predictor

No pre-processing
Resampling: Bootstrapped (25 reps)
Summary of sample sizes: 50, 50, 50, 50, 50, 50, ...
Resampling results:

RMSE Rsquared
15.16135 0.6679958

Tuning parameter 'intercept' was held constant at a value of TRUE

 

cars.lm のサマリーを表示。ここは普通に lm関数を使った時と同じかと。

> summary(cars.lm)

Call:
lm(formula = .outcome ~ ., data = dat)

Residuals:
Min 1Q Median 3Q Max
-29.069 -9.525 -2.272 9.215 43.201

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -17.5791 6.7584 -2.601 0.0123 *
speed 3.9324 0.4155 9.464 1.49e-12 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 15.38 on 48 degrees of freedom
Multiple R-squared: 0.6511, Adjusted R-squared: 0.6438
F-statistic: 89.57 on 1 and 48 DF, p-value: 1.49e-12

 

散布図に回帰直線を引く際は "lattice" パッケージ中の "xyplot関数" を使用します。
"lattice" パッケージは "caret" をロードする際に合わせてロードされます。

> xyplot(dist ~ speed, data = cars, type = c("p", "r"), col.line = "red",
+ main = "speed x dist (cars)")

 

f:id:ngyope:20160829235947j:plain