15
「ビジネス活用事例で学ぶ データサイエンス入門」輪読会 #2 第4章 どの属性の顧客が離脱しているのか? 2016/1/11

ビジネス活用事例で学ぶデータサイエンス入門 #2

Embed Size (px)

Citation preview

Page 1: ビジネス活用事例で学ぶデータサイエンス入門 #2

「ビジネス活用事例で学ぶ データサイエンス入門」輪読会

#2

第4章 どの属性の顧客が離脱しているのか?

2016/1/11

Page 2: ビジネス活用事例で学ぶデータサイエンス入門 #2

自己紹介

しまじろう よう SIer で SE(金融・情報系) ⇒ 個人事業主 ソーシャルゲームベンチャーでデータ解析者・PM を担当 現在は不動産仲介プラットフォーム企業で解析基盤周りのお仕事をしています C#/Ruby/R/Rails/DB 数学/統計・機械学習/経営/マーケティング ※中小企業診断士を取得予定

Twitter: you_s1025

2

Page 3: ビジネス活用事例で学ぶデータサイエンス入門 #2

問題の発生

リリース後1年3ヶ月

前月比でユーザ数が減少

原因の解明と対策!

3

Page 4: ビジネス活用事例で学ぶデータサイエンス入門 #2

問題の特定までの流れ1.問題発生&仮説 x 3 A.プロモーションに問題 B.イベントが退屈 C.何らかのユーザセグメントに問題あり

2.消去法により上記 C. を支持 3.データの前処理 4.属性別分析 性別 ⇒ 問題なし 年代 ⇒ 問題なし 性別 x 年代 ⇒ 問題なし デバイス ⇒ 問題あり 日次の UU 推移をグラフで確認 ⇒ 9月半ばから Android で問題発生

4

Page 5: ビジネス活用事例で学ぶデータサイエンス入門 #2

前処理

DAUlog_date app_name user_id2013-08-01 game-01 337542013-08-01 game-01 28598

2013-08-01 game-01 30306

# csv の読込 dau <- read.csv("DL76333/R/section4-dau.csv", header=T, stringsAsFactor=T) user_info <- read.csv("DL76333/R/section4-user_info.csv", header=T, stringsAsFactors=T)

UserInfoinstall_date app_name user_id gender generation device_type

2013-08-01 game-01 33754 M 20 iOS2013-07-16 game-01 28598 M 50 iOS

2013-07-20 game-01 30306 F 30 iOS

# 2テーブルの結合 dau.user.info <- merge(dau, user.info, by=c("user_id", "app_name"))

# 月の情報を追加 dau.user.info$log_month <- substr(dau.user.info$log_date, 1, 7)

DAU-UserInfouser_id app_name log_date install_date gender generation device_type log_month

33754 game-01 2013-08-01 2013-08-01 M 20 iOS 2013-08

28598 game-01 2013-08-01 2013-07-16 M 50 iOS 2013-08

30306 game-01 2013-08-01 2013-07-20 F 30 iOS 2013-08

5

Page 6: ビジネス活用事例で学ぶデータサイエンス入門 #2

属性別分析: 性別# 1-1. 性別で分類 tbl.gender <- table(dau.user.info[, c("log_month", "gender")]) barplot(tbl.gender) # 棒グラフをプロット

# 1-2. 軸の入れ替え t(tbl.gender) barplot(t(tbl.gender))

# 1-3. 100分率の積み上げグラフで確認 t(sweep(tbl.gender, 1, rowSums(tbl.gender), "/") * 100) barplot(t(sweep(tbl.gender, 1, rowSums(tbl.gender), "/") * 100))

性別ごとの推移(8月⇒9月)以外でも確認

※t (転置)関数でデータの縦と横を入れ替える 月ごとの絶対値では分かりづらい?

sweep/rowSums 関数で各列と行の総和との比を計算 ⇒ 問題が無い事を確認 ※sweep, rowSums 関数については補足を参照

6

Page 7: ビジネス活用事例で学ぶデータサイエンス入門 #2

属性別分析: 年代# 2-1. 年代で分類 tbl.generation <- table(dau.user.info[, c("log_month", "generation")]) barplot(tbl.generation)

# 2-2. 軸の入れ替え t(tbl.generation) barplot(t(tbl.generation))

# 2-3. 100分率の積み上げグラフで確認 t(sweep(tbl.generation, 1, rowSums(tbl.generation), "/") * 100) barplot(t(sweep(tbl.generation, 1, rowSums(tbl.generation), "/") * 100))

年代ごとの推移(8月⇒9月)以外でも確認

※t (転置)関数でデータの縦と横を入れ替える 月ごとの絶対値では分かりづらい?

sweep/rowSums 関数で各列と行の総和との比を計算 ⇒ 問題が無い事を確認

7

Page 8: ビジネス活用事例で学ぶデータサイエンス入門 #2

属性別分析: 性別 x 年代# 3-1. 年代で分類 dcst.gender_generation <- dcast(dau.user.info,log_month~gender+generation, value.var="user_id", length) barplot(as.matrix(dcst.gender_generation[, -1]))

# 3-2. 軸の入れ替え t(as.matrix(dcst.gender_generation[, -1])) barplot(t(as.matrix(dcst.gender_generation[, -1])))

# 3-3. 100分率の積み上げグラフで確認 t(sweep(dcst.gender_generation[, -1], 1, rowSums(dcst.gender_generation[, -1]), "/") * 100) barplot(t(sweep(dcst.gender_generation[, -1], 1, rowSums(dcst.gender_generation[, -1]), "/") * 100))

性別x年代ごとの推移(8月⇒9月)以外でも確認

sweep/rowSums 関数で各列と行の総和との比を計算 ⇒ 問題が無い事を確認

※t (転置)関数でデータの縦と横を入れ替える 月ごとの絶対値では分かりづらい?

8

Page 9: ビジネス活用事例で学ぶデータサイエンス入門 #2

属性別分析: デバイス# 4-1. デバイスで分類 tbl.device <- table(dau.user.info[, c("log_month", "device_type")]) barplot(tbl.device)

# 4-2. 軸の入れ替え t(tbl.device) barplot(t(tbl.device))

# 4-3. 100分率の積み上げグラフで確認 t(sweep(tbl.device, 1, rowSums(tbl.device), "/") * 100) barplot(t(sweep(tbl.device, 1, rowSums(tbl.device), "/") * 100))

デバイスごとの推移(8月⇒9月)以外でも確認

※t (転置)関数でデータの縦と横を入れ替える 月ごとの絶対値では分かりづらい?

sweep/rowSums 関数で各列と行の総和との比を計算 ⇒ 9月の比率が明らかに8月と異なる

9

Page 10: ビジネス活用事例で学ぶデータサイエンス入門 #2

属性別分析: デバイス > 日次 UU 推移# 日付xデバイス の単位でユーザ数を算出 dau.user.info.device.summary <- ddply(dau.user.info, .(log_date, device_type), summarize, dau=length(user_id))

# log_date を日付型へ変換 dau.user.info.device.summary$log_date <- as.Date(dau.user.info.device.summary$log_date)

# 折れ線グラフの描画 ggplot(dau.user.info.device.summary, aes(x=log_date, y=dau, col=device_type, lty=device_type, shape=device_type)) + geom_line(lwd=1) + geom_point(size=4) + scale_y_continuous(label=comma, limits=c(0, max(dau.user.info.device.summary$dau)))

Android の減少が原因

これまでの分析で Android に問題がありそうな事が分かってきたので本当に9月に問題が発生しているのか

を日次 UU の推移で確認

9月の2週辺りから明らかに減少

10

Page 11: ビジネス活用事例で学ぶデータサイエンス入門 #2

まとめ

11

1.問題解決への道筋 1.問題発生に対し仮説を立てる(発散) 2.ヒアリングその他により仮説を絞り込む(集約) 3.必要なデータを揃えて分析の準備を整える 4.絞り込んだ仮説に従ってデータを分析 5.原因の候補を見つけたらさらに深掘りして確度を上げる 6.得られた知見を元に関係部門と連携

2.クロス集計を活用する 1.2次元のクロスが基本 2.3次元以上のクロスも dcast 関数で扱う事が可能

3.可視化は大事 1.棒グラフ 2.時系列の折れ線グラフ

Page 12: ビジネス活用事例で学ぶデータサイエンス入門 #2

補足: sweep 関数

12

sweep(x, MARGIN, STATS, FUN=“-“) • x: データ • MARGIN: STATS を適用する方向 1:列 / 2:行 • STATS: 適用する統計量 • FUN: 演算子 or 関数 ※デフォルトは “-“(減算)

データと統計量との演算を行/列ごとに実施

# 3x5行列を生成 A <- matrix(1:15, 3)

# 各行を1サンプルとする偏差の算出 sweep(A, 1, apply(A, 1, mean))

# 各列の総和に対する比率の算出 ※列ごとに値の合計値が100(%)になる sweep(A, 2, colSums(A), "/") * 100

Page 13: ビジネス活用事例で学ぶデータサイエンス入門 #2

補足: rowSums/colSums 関数

13

各行(列)ごとに総和を算出rowSums(x) / colSums(x) • x: データ

# 3x5行列を生成 (A <- matrix(1:15, 3)) [,1] [,2] [,3] [,4] [,5] [1,] 1 4 7 10 13 [2,] 2 5 8 11 14 [3,] 3 6 9 12 15

# 行/列 ごとの総和を計算 [1] 6 15 24 33 42rowSums(A) #=> [1] 35 40 45 colSums(A) #=> [1] 6 15 24 33 42

Page 14: ビジネス活用事例で学ぶデータサイエンス入門 #2

補足: merge 関数①

14

2つのデータを結合するmerge(x, y, by, all) • x: データ1 • y: データ2 • by: 結合に用いる項目(キー)名を配列で指定

• by.x: x 側で用いる結合のキーを指定 ※x, y 側で項目名が異なる場合に使用 • by.y: y 側で用いる結合のキーを指定 ※x, y 側で項目名が異なる場合に使用 • by: x, y 共に指定された結合のキーを用いる

• all: 結合する際に主軸とするデータ(x, y)を指定 • all.x=TRUE ⇒ x に y を紐付ける ※左外部結合に相当 • all.y=TRUE ⇒ y に x を紐付ける ※右外部結合に相当 • all=T ⇒ x, y の両方が主軸になる ※両側外部結合に相当 ※指定しない場合は内部結合に相当

# データの準備 x <- data.frame(id=1:5, value=seq(10, 50, 10)) y <- data.frame(key=4:8, score=seq(400, 800, 100))

xid value1 10

2 20

3 30

4 40

5 50

ykey scoer4 400

5 500

6 600

7 700

8 800

Page 15: ビジネス活用事例で学ぶデータサイエンス入門 #2

補足: merge 関数②

15

y

x#内部結合: 合致する行だけが残る merge(x, y, by.x=“id”, by.y=“key”)

id value score4 40 400

5 50 500

#左外部結合: x の側だけ全て残る merge(x, y, by.x=“id”, by.y=“key”, all.x=T)

id value score1 10 NA

2 20 NA

3 30 NA

4 40 400

5 50 500

#両側外部結合: x, y の両方とも全て残る merge(x, y, by.x=“id”, by.y=“key”, all=T)

id value score1 10 NA

2 20 NA

3 30 NA

4 40 400

5 50 500

6 NA 600

7 NA 700

8 NA 800

#右外部結合: y の側だけ全て残る merge(x, y, by.x=“id”, by.y=“key”, all.y=T)

id value score4 40 400

5 50 500

6 NA 600

7 NA 700

8 NA 500

T

T

F

F