RGAでページビュー数 VS 滞在時間 の散布図を描く

RGAというRのgoogle analytics用ライブラリがあります。
このライブラリを使って、google analyticsのデータを出力してみます。題材としては、GAのウェブUIで見られる平均の指標である滞在時間とページビューではなく、滞在時間とページビューそのまののデータを出力し、plotします。

データの取得

具体的な取得項目名は、ディメンジョン側にvisitLengthとpageDepathを使います。 指標側のtimeOnSiteやpageviewsではありません。個別に分類して見たい場合はディメンジョンを指定して、欲しい指標を取ります。今回の欲しい指標は訪問数(visits)になります。
また、新規・リターンユーザー別のvisitorTypeでのデータの違いを見るために、ディメンジョンにvisitorTypeを指定します。
これで、データとして、滞在時間(秒数), ページビュー数, 新規・非新規別の訪問数がでます。

データの加工

今回は散布図にしたいので、訪問数分だけ、データの行を複製します。
(*そのままでも、バブルチャート表示用のデータになります)
今回は、粒度の細かいデータに変換します。
その後、グラフで出力します。

以下が、その出力したグラフになります。

pageDepth_visitLength_in_googleAnalaytics1
まずは、普通にplotです。↑ y軸対数表示log10でした。マイナスは一分以下
pageDepth_visitLength_in_googleAnalaytics2
次にggplotです。↑
pageDepth_visitLength_in_googleAnalaytics3
次に平均をラインで。↑
(前のグラフに重ね書きする方法がわからなかった)

以下は、コードです。
認証部分 + プロファイルID は各自で埋めて下さい。

library(rga)
rga.open(instance = "ga",
         where = "/home/shirai/rga/shirai/.ga",
         client.id = "指定してください", 
         client.secret = "指定してください")
start.date = "2011-03-30"
end.date = "2013-04-14"
ID <- "ga:指定してください"
dt <- ga$getData(ID, start.date, end.date,
                 dimensions="ga:visitLength,ga:pageDepth,ga:visitorType",
                 metrics = "ga:visits,ga:timeOnSite,ga:pageviews",batch=TRUE)

##散布図用にデータを拡張?する
ret <- dt[unlist(lapply(1:nrow(dt), function(i)rep(i, dt[i,4]))),]
dt0 <- dt[,c("visitLength","pageDepth","visits")]
ret0 <- dt0[unlist(lapply(1:nrow(dt0), function(i)rep(i,dt0[i,3]))),]
for(i in 1:2)ret[,i] <- as.numeric(ret[,i])

##通常のplot表示
png(file="~/tmp/pageDepth_visitLength_in_googleAnalaytics1.png")
plot(ret$pageDepth, log(ret$visitLength/60,10),xlab="ページビューー数",ylab="滞在時間(分)")
dev.off()
##アウトプットがイマイチ
## alphaを入れて、jitterを入れる
p <- ggplot(ret[ret$visitLength!=0 & ret$visitLength<1200 & ret$pageDepth<16,],
            aes(pageDepth,visitLength/60, colour=visitorType))
png(file="~/tmp/pageDepth_visitLength_in_googleAnalaytics2.png")
p + geom_point(alpha=1/10,position="jitter") + xlab("ページビュー数") + ylab("滞在時間(分)")
dev.off()

## 平均で見る。前のグラフにimposeする方法わからず、、、
avgSOT <- ddply(dt, .(as.numeric(pageDepth),visitorType), summarise, ats= sum(as.numeric(timeOnSite)/sum(as.numeric(visits))))
names(avgSOT) <- c("pageDepth","visitorType","AvgTimeOnSite")
png(file="~/tmp/pageDepth_visitLength_in_googleAnalaytics3.png")
ggplot(avgSOT[avgSOT$pageDepth<16,], aes(pageDepth, AvgTimeOnSite/60, color=visitorType))+geom_line() + xlab("ページビュー数") + ylab("滞在時間(分)")
dev.off()

ページ遷移データをグルーピング化する

フォーラムで質問を見かけました。
パラメータが付いたURLで、パラメータを除いた合計での遷移数
GAのウェブUI上でページグループの遷移のセッション数を出す方法も回答してありますので、上記のリンク先をご覧下さい。

ページ間の遷移データ(pageviewが指標となる)をいろいろな条件でグルーピング化するという命題だと思います。

この間作った自作のツールを使うと便利にできます。
データ項目は、指標: pageviews ディメンジョン:previousPagePath, nextPagePath
(*nextPagePathはpagePathでも同じ)
PV数ベースではなく、セッション数ベースの値が欲しい時は、指標をuniquePageviewsにして下さい。
その後、expression filterというところで、LIKE演算子を使って絞り込みをします。

CARTで結論を絞る

cart

Google Analyticsでエクセルなどでデータをいじる場合、 僕がよくやったのは、ディメンジョンを多めにセットしておいて(データ行は一万行を超えないようにする、indexするのが面倒な場合)、データを得た後、エクセルのピボットで軸を入れ替えながら、突出したポイントを探すことでした。エクセル2010でスライサー使えば、アドバンスセグメント+カスタムレポートという形が簡単かつ柔軟に実現できる。

それで、データに浸かっていじってれば、そのうち、イメージができることはできるけど、時間かかります。 そういう場合に、よく言われるのは、予め仮説を持って、その検証のみに時間を使う。サイトに対する今までの見識を持って仮説を出し、データでの裏付けを探す。見識がなければ、世間で一般的に使われる指標を一般的なディメンジョンで分類するという形になると思います。または、テストできる環境を整え、指標を対比する。。。などだったと思います。

で、それとは違うアプローチとして、データマイニングがあります。仮説なしで、結論みたい?なものをだしてもらう。ほとんどは凡庸な結論だけど、時々、宝ものが出てくるかもしれない。。。冒頭の本は、そのアプローチ、データマイニングのやり方を説明してくれてます。この本は、数式抜きでやり方を丁寧に説明してくれてるし、書き方からも読者に理解させようとする気が伝わってきます。とても良いです。


で、その中の分析木をやってみました。ただ、分析木は、マイニングというより、シンプルな結論の提示という気がします。なので、この本にあるように、mvpartというライブラリを使います。コードは最後に提示します。

冒頭のグラフが図で、結果そのものが下記。
split:分岐基準、n:その基準での観察数(セッション数), loss: n回は間違え分類した。(分類名が続いてる。今回なら、bounce, nobounces)

========================================================

n= 226

node), split, n, loss, yval, (yprob)
* denotes terminal node

1) root 226 79 bounce (0.65044 0.34956)
2) visitCount>=6.5 22  1 bounce (0.95455 0.04545) *
3) visitCount< 6.5 204 78 bounce (0.61765 0.38235)
6) landingPagePath=/cookie/utma,2010-03-11-16-53,igation_analysis,ng-apis/gaq-push 132 41 bounce (0.68939 0.31061)
12) visitCount< 3.5 130 39 bounce (0.70000 0.30000) *
13) visitCount>=3.5 2  0 nobounce (0.00000 1.00000) *
7) landingPagePath=/ 72 35 nobounce (0.48611 0.51389)
14) medium=(none),organic 48 22 bounce (0.54167 0.45833)
28) visitCount< 4.5 44 19 bounce (0.56818 0.43182) *
29) visitCount>=4.5 4  1 nobounce (0.25000 0.75000) *
15) medium=referral 24  9 nobounce (0.37500 0.62500)
30) visitCount>=2.5 2  0 bounce (1.00000 0.00000) *
31) visitCount< 2.5 22  7 nobounce (0.31818 0.68182) *

=========================================================

226セッションで79が直帰と間違え分類で、
訪問回数で6,5で分かれて(22(間違え1) – 204(間違え78))
ランディングページで分かれて、(トップページと、それ以外, 132 – 72)
その子供たちは、また訪問回数やら、メディアやらで分岐される。

数字自体は、まあそうだろうなあ、、というもので、それで終わりだけど、ガイドラインにはなると思う。

分類項目の設定は、こちらで決めたり、訪問回を連続変数にしたりしてるのは、予断があるわけだし、最大の問題点として、分析単位がセッションになっていて、ユーザー単位になってない点があります。同一のユーザーが複数回記録されているデータというのは留保しないといかん。

ただ、それでも、ある一定の基準に沿って、ディメンジョンの項目を整理して、差異の大きい部分だけを抽出しているので、データから結論を得るプロセスとしていいのではないかなと思います。

あと、枝分かれの基準のジニ係数の計算をちょこっとだけやってみる。
(詳しく(正しく?)は、上記の本、データマイニング入門の本を読んでください)

最初の枝分かれは、訪問回数の6.5 ト表示なので、1-6, 7以上と分かれてる。

そのジニ係数は、

7回以上で  1 – ((22/23)^2 + (1/23)^2) => 0.087

6回以下で  1- ( (78/204)^2 + (126/204)^2) => 0.472

これを加重して、(23/226) * 0.087 + (204/226) * 0.472 =>  0.435

元々のルートのジニ係数は、1 – ((79/226)^2 + (147/226)^2) => 0.455

なので、分岐基準は、0.02となる。他の切れ目でやって、分岐基準が小さくなることを確認したいけど、パスします。。。

以下コード。
RGoogleAnalyticsは、cranにはないので、ダウンロードしてinstallする。
あとは、email, password, tableidを、各自でセットするれば、同じように動くと思う。画像ファイルの保存場所と。

library(RGoogleAnalytics)
library(mvpart)

##GAのデータを取得する
ga <- RGoogleAnalytics()
ga$SetCredentials(mailaddress, password)
query <- QueryBuilder()
query$Init(start.date = "2011-01-01",
           end.date   = "2011-12-15",
           dimensions = "ga:medium,ga:region,ga:date,ga:hour,ga:visitCount,ga:landingPagePath",
           metrics    = "ga:entrances,ga:bounces",
           sort       = "ga:date",
           table.id   = "ga:xxxxxxxxx")
data <- ga$GetReportData(query)$data

##データの整理
if(!is.null(data$visitCount)) data$visitCount <- as.numeric(data$visitCount)
data$date <- as.Date(data$date, "%Y%m%d")
data$wday <- weekdays(data$date)
data$wnum <- format(data$date, "%w")

##Langind Pageを上位(entrance数)5つに絞る
top5.lp <- arrange(
                   ddply(data, .(landingPagePath), summarise, sum=sum(entrances)),
                   -sum
                   )[1:5,"landingPagePath"]
dt0 <- subset(data, landingPagePath %in% top5.lp)
##URLが長いのがあるので、後ろから15文字だけにする
dt0$landingPagePath <- sapply(dt0$landingPagePath, function(x){ l <- nchar(x); substr(x, l-15, l)})

##top5.reg <- arrange(ddply(data, .(region), summarise, sum=sum(entrances)), -sum)[1:5, "region"]
##dt1 <- subset(dt0, region %in% c("Tokyo","Osaka","Aichi","Fukuoka","Kanagawa"))

##1セッションで1レコードの形にする
dt0 <- within(dt0, nobounces <- entrances-bounces)
a0 <- adply(dt0, 1, function(x)data.frame(engage=rep("bounce",x$bounces)))
a1 <- adply(dt0, 1, function(x)data.frame(engage=rep("nobounce",x$nobounces)))
dt0 <- rbind(a0,a1)

##いらないディメンジョン、指標を外しておく。以下の書式?なら元から無い項目でもOK
dt0 <- dt0[, !names(dt0) %in%
           c("visits","bounces","nobounces","date","region","hour","wday","wnum","entrances")]

##RPARTの部分
ret <- rpart(engage ~ ., data=dt0, method="class",cp=0.01)
png("~/Dropbox/cart.png",width=800,height=600)
rpart:::plot.rpart(ret, uniform=T, branch=1, margin=0.15)
rpart:::text.rpart(ret, all=T,pretty=0,fancy=T,digits=3,use.n=T)
dev.off()
plotcp(ret)