廿TT

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

ブートストラップまがいの方法による "(not provided)" の推定

前回前々回Google アナリティクスから検索キーワードのデータをとってきたけど、" (not provided) " をスルーしていた。

これは「検索キーワードが取得できませんでした」という意味なので他のキーワードと同じ扱いはできない。
かといって取り除いてしまうのも(場合によっては)問題がある。

そこで、" (not provided) " を推定してやろう。

Googleアナリティクスにログインし、「標準レポート」をクリックし、左メニューの「トラフィック」→「検索」→「オーガニック検索」をクリックします。次に「not provided」をクリックし、「セカンダリディメンション」をクリックし、「トラフィック」内の「ランディングページ」をクリックします。

一定のオーガニック検索による訪問者がいる場合、「not provided」となっていて検索キーワードがわからなくても、他にてがかりとなるキーワードが計測できているはずですので、ある程度キーワードを推測する事ができます。
検索キーワードに表示されるnot providedとは?Googleアナリティクス

とのこと。
たしかに、同じページにたどり着いたからには、同じようなキーワードで検索していたんだろう、と推測するのは不自然じゃないと思う。
なのでそれをやろう。


検索キーワードごとの訪問数はこんな感じ。
f:id:abrahamcow:20130708002731p:plain

" (not provided) " がとても多い。


ぼくが考えた " (not provided) " の推定方法はバカみたいに単純。

たとえば、ページ "http://aaaaushisan.blogspot.jp/2012/03/r-sort-order.html" に訪れた人の検索キーワードはこんなものだった。

キーワード 訪問数
(not provided) 70
r order 17
r sort 4
r ソート 4
order+r 3
order by sort 違い 1
order r 1
order+sort 違い 1
r order 並べ替え 1
r order 例 1
r with order 1
r 整列 元の 1
r 並び替え 1
r 並べ替え 1
r 並べ変え 1
r+order 1
r+sort+order 1
r+関数+order 1
r並べ替え 1
to in order to 違い 1

これらのうち、 "(not provided)" 以外のキーワードを訪問数のぶんだけ並べる。

{r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r order,r sort,r sort,r sort,r sort,r ソート,r ソート,r ソート,r ソート,order+r,order+r,order+r,order by sort 違い,order r,order+sort 違い,r order 並べ替え,r order 例,r with order,r 整列 元の,r 並び替え,r 並べ替え,r 並べ変え,r+order,r+sort+order,r+関数+order,r並べ替え,to in order to 違い}

この集合の中から "(not provided)" の訪問数ぶん、70回ランダムに復元抽出*1でキーワードをとってくる。

それを "(not provided)" の推定キーワードにしてしまう。

ただしもし訪れた人のキーワードがぜんぶ "(not provided)" になっているページがあれば、そのときはしょうがないので、"(not provided)" をそのまま残す。

そうやってやってみた結果がこちら。

f:id:abrahamcow:20130708004551p:plain

だからなんだという話ではあるし、これにどういう意味があるのかもよくわからないし、計算効率も悪い。

でも、なんかこの辺におもしろい問題が眠ってそうな気がした。

以下が R のコード。

dat1 <- read.csv(
  "Analytics すべてのウェブサイトのデータ オーガニック検索トラフィック 20130606-20130706.csv"
  ,stringsAsFactors = FALSE
)
#csvファイルの最初(ヘッダ)と最後(フッダ)はあらかじめ消してある。
#head(dat1)
kw <-as.factor(dat1[,1])
tab1 <-tapply(dat1[,3], kw, sum)
tab1 <-sort(tab1)
kw2 <- as.numeric(tab1)
names(kw2) <- names(tab1)
kw3 <- c(sum(kw2[kw2==1]), kw2[kw2>1])
#訪問回数が 1 のものは「その他」にした。
names(kw3)[1] <- "その他"
#nihongo()
dotchart(kw3, pch=16,xlab="訪問数")
#最初のグラフ
#
lp <-dat1[dat1[,1]=="(not provided)",2]
npkw <- character(0)
l <- length(lp)
for(i in 1:l){
  tmp <- dat1[dat1[,2]==lp[i], c(1,3)]
  subtmp <- tmp[tmp[,1]!="(not provided)",]
  if(dim(subtmp)[1]==0){
    npkw <- c(npkw,rep(tmp[,1],tmp[,2]))
  }else{
    npkw <- c(npkw,
            sample(rep(subtmp[,1],subtmp[,2]), 
                   tmp[tmp[,1]=="(not provided)",2] , 
                   replace=TRUE)
    )
  }
}
tab_np <- table(npkw)
tmp2 <- kw3[names(kw3) != ("(not provided)")]
l<-length(tmp2)
for(i in 2:l){
  flg <- names(tmp2)[i]==names(tab_np)
  if(all(!flg)){
    tmp2[i] =tmp2[i] + 0  
  }else{
    tmp2[i] =tmp2[i] + tab_np[flg]
  } 
}
kw_est <- c(tmp2, tab_np[names(tab_np)=="(not provided)"])
#nihongo()
dotchart(kw3, pch=16,xlab="訪問数")
points(kw_est, 1:length(kw3))
legend("bottomright",pch=c(16,1), legend=c("実測値","推定値"))
#

参考:
グラフの例:ドットプロット

*1:例えばくじ引きは一回とってくるごとにくじが一本ずつ減っていくので非復元抽出と呼ぶ。これに対してサイコロは六が何回でても六が減るわけじゃないので復元抽出と呼ぶ。くじを一回引くたびにまたもとに戻したら → 復元抽出