廿TT

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

[searchConsoleR]検索キーワードの階層型クラスタリング

今日の川柳

本当は 収集したキーワードをグループ化する | 検索連動型広告を成功に導くSEM戦略 | Web担当者Forum の逆問題がやりたいけど攻めあぐねている。

キーワードの距離

どこからどこまでを一つのキーワードとみなすかは難しいですが、ここでは単純に検索クエリ内のスペースで区切られた文字列を「キーワード」とみなします。形態素解析とかはしません。

 u_m (m=1,\ldots,M) をユニークなキーワードとします。

q_n (n=1,\ldots,M) を検索クエリとします。q_n はキーワードの集合です。語順は無視します。

キーワード u_iu_j の類似度を、掛け合わせられたキーワードが一致するクエリの個数、すなわち

 (q_k \setminus u_i)=(q_l \setminus u_j), ( k \neq l)

を満たす組 (k,l) の個数とします。

類似度の逆数をとって、指数関数の中に入れたものをキーワード間の距離とします。

この距離行列を使って、ウォード法(Rとクラスター(1))でクラスタリングしてみました。

結果

対象ページは 花合わせの遊び方:よい子とよい大人のための花札入門 - 廿TT にしました。

クラスタ数は勘と経験から6にしました。

f:id:abrahamcow:20180411210318p:plain

デンドログラムを見ると、左の方に「ふたり」とか「三人」とかの人数を表す語句が固まっていたり、右のほうに「こいこい」「花合わせ」などの花札のメジャーな遊び方を指す語句が固まっていたりするので、まあまあ妥当かなと思います。

ついでに、人数系のワードを含むクエリと含まないクエリで、クリックやCTRを見てみます。

f:id:abrahamcow:20180411210816p:plain

いずれの指標も、人数系のワードを含むTRUEのほうが良好な数字で、このへんにユーザーのニーズがあると言えそうです。

以下に R のコードを貼ります。

library(searchConsoleR)
library(tidyverse)

scr_auth()
sc_websites <- list_websites()

scdata <- search_analytics(sc_websites[1,1],
                           dimensions = c("query"),
                           dimensionFilterExp = "page~~/entry/2015/01/17/064522")

make_distance_matrix <- function(query){
  query_list <-sapply(scdata$query,function(x)strsplit(x," "))
  tab1 <-table(unlist(query_list))
  kw <-names(tab1[tab1>1])
  BoW <-t(sapply(query_list,function(x){kw %in% x}))
  BoW <- BoW[apply(BoW,1,any),]
  colnames(BoW) <- kw
  M <- length(kw)
  simmat <- matrix(0,M,M)
  for(j in 1:M){
    for(i in 1:M){
      if(i != j){
        list1 <- apply(BoW[BoW[,i],-i],1,which)
        list2 <- apply(BoW[BoW[,j],-j],1,which)
        simmat[i,j] <-length(intersect(list1,list2)) 
      }
    }
  }
  colnames(simmat)<-kw
  rownames(simmat)<-kw
  list(query_list=query_list,distmat=exp(-simmat))
}
out1 <-make_distance_matrix(scdata$query)
hc1<-hclust(as.dist(out1$distmat),method="ward.D")
#png("tree1.png", width=800, height = 800)
#par(family="Osaka")
plot(hc1,main="",xlab="")
rect.hclust(hc1,k=6)
#dev.off()

cl1 <-cutree(hc1,k=6)

scdata2 <-scdata %>% 
  mutate(number=sapply(out1$query_list, function(x)any(x %in% names(cl1)[cl1==1]))) %>% 
  gather(metrics,value,-number,-query)

p1 <-ggplot(scdata2,aes(x=number,y=log(value+0.5,2)))+
  geom_boxplot()+
  facet_wrap(~metrics,scales = "free_y")
print(p1)
#ggsave("boxplot.png",p1)

検索連動型広告を成功に導くSEM戦略 増補改訂版

検索連動型広告を成功に導くSEM戦略 増補改訂版

検索にガンガンヒットさせるSEOの教科書

検索にガンガンヒットさせるSEOの教科書