廿TT

譬如水怙牛過窓櫺 頭角四蹄都過了 因甚麼尾巴過不得

CVR、新規率、直帰率と「誤差の範囲」(信頼区間付き折れ線グラフ)

追記:関数化しました。

abrahamcow.hatenablog.com

分母が違う場合の「割合」の比較

Web 解析の分野ではしばしば、なにかをなにかで割った値、「割合」を定期的に観察することが行われます。

なかでもよく使われる指標は CVR(コンバージョンレート)、直帰率bounce rate)、新規率(新規訪問の割合)などでしょうか。

しかし、この割合というのはなかなか曲者です。

100人中50人が「yes」と答えた場合と、2人中1人が「yes」と答えた場合は、どちらも「yes」の割合は50%ですが、100人中50人のほうが、より信憑性が高い50%と考えられます。

分母が大きく違う場合、割合を単純に大小で比較することは意味がありません。

そこで私は、割合に「信頼区間」を併記することを推奨します。
信頼区間は観測値の誤差を表すための方法の一つです。

「誤差の範囲」という言葉は文脈によって大きく意味が異なるので注意が必要ですが、ここではあえて大雑把に説明しています。ご容赦ください。


誤差の範囲とはなにか? - 廿TT

R + Google アナリティクスによる実践

まずは APIGoogle アナリティクスからデータを取得します。

library("RGoogleAnalytics")
query <- QueryBuilder()
access_token <- query$authorize()

ここでアクセストークンをコピペ。
RGoogleAnalytics をいじっている - 廿TT を参照。)

ga <- RGoogleAnalytics()
ga.profiles <- ga$GetProfileData(access_token)

sta ="2013-05-01"
en ="2014-09-30"

query$Init(start.date = sta,
           end.date = en,
           dimensions = "ga:yearMonth,ga:userType",
           metrics = "ga:sessions,ga:bounces,ga:goal2Completions",
           table.id = paste("ga:",ga.profiles$id[1],sep="",collapse=","),
           access_token=access_token)

dat1 <- ga$GetReportData(query)

dat2 <- aggregate(by=list(dat1$yearMonth), dat1[3:5], sum)
t1 <-seq.Date(as.Date(sta),as.Date(en),by="1 month")

以上でデータ取得・整形は完了。

信頼区間を求める関数を定義。

CIset<-function(k, n, group=NULL, conf=0.95){
  rate = k/n
  len <-length(k)
  CI =sapply(1:len ,function(i){
    ans <- binom.test(k[i], n[i], conf.level =conf)
    ans$conf.int[1:2]})
  data.frame(group =if(is.null(group)){LETTERS[1:len]}else{group},
             rate=rate,
             upper = CI[1,],
             lower = CI[2,])
}

作図。
まずは CVR のグラフを書いてみます。

library(ggplot2)
library(scales)

theme_set(theme_bw(base_size=15, base_family="HiraKakuProN-W3")) 
#日本語フォントを指定

cvrate <- CIset(dat2$goal2Completions, dat2$sessions,group=t1)

p1 <- ggplot(cvrate, aes(x=group,y=rate))  +
  geom_line()+
  scale_x_date(labels = date_format("20%y/%m")) +
  scale_y_continuous(labels = percent) +
  labs(x="", y="CVR")
p1 + geom_ribbon(aes(ymin=lower,ymax=upper),alpha=0.3,fill="blue4")
#alpha は透明度

f:id:abrahamcow:20141014182555p:plain

黒い折れ線が CVR の観測値、リボン状に青く色づけした部分が95%信頼区間です。
2013/7 は観測値だけをみると CVR が高くなっていますが、信頼区間の幅が広いです。
すなわち、2013/7 は分母の訪問数自体が小さいがために、たまたま CVR が高くなってしまっただけ、という可能性が高いと解釈できます。

このようなグラフを書くことで「7月は CVR が改善した! なぜだ?」という問いに「偶然では」という示唆を与えることができます。

信頼区間を示すのにエラーバーという下記のような表現を使うこともあります。

p1 + geom_errorbar(aes(ymin=lower,ymax=upper), colour="grey40")

f:id:abrahamcow:20141014181007p:plain

でも半透明のリボンのほうがかっこいいので、今回はリボンを採用することにします。


直帰率の図示。

brate <- CIset(dat2$bounces, dat2$sessions,group=t1)

ggplot(brate, aes(x=group,y=rate))  +
  geom_line()+
  scale_x_date(labels = date_format("20%y/%m")) +
  scale_y_continuous(labels = percent) +
  labs(x="", y="直帰率") + 
  geom_ribbon(aes(ymin=lower,ymax=upper),alpha=0.3,fill="red4")

f:id:abrahamcow:20141014182617p:plain


新規率の図示。

sub1 <- subset(dat1,userType=="New Visitor")
nrate <- CIset(sub1$sessions, dat2$sessions,group=t1)

ggplot(nrate, aes(x=group,y=rate))  +
  geom_line()+
  scale_x_date(labels = date_format("20%y/%m")) +
  scale_y_continuous(labels = percent) +
  labs(x="", y="新規率") + 
  geom_ribbon(aes(ymin=lower,ymax=upper),alpha=0.3,fill="orange")

f:id:abrahamcow:20141014182632p:plain