plyrで集計 ggplot2でグラフ化

Rを使ったアクセスデータの集計(1)

plyrとggplotを使ってます。
(*)Rを勉強し始めたら、早めにplyrとggplot2を覚えるのが吉。
見通しがよくなると思います。アクセス数値の集計というより、Rの勉強エントリ。

複数の指標を時系列で並べる

アクセスの基本的な数値を集計して、同じ時間軸で並べます。
以下のものを図示します。まず下準備。認証まで

コード(認証)

#RGoogleAnalyticsをファイル内にダウンロードしておいて使う。
source("/home/shirai/ga/r/RGoogleAnalytics/R/RGoogleAnalytics.R")
source("/home/shirai/ga/r/RGoogleAnalytics/R/QueryBuilder.R")

#今回の目的のggplot2、同時に plyrとreshapeもloadされる。
library(ggplot2)

#オブジェクト的な使い方? dataframeの要素に関数がある
ga <- RGoogleAnalytics()
#mail, pwを自分の設定ファイルから取得する
ac <- read.csv("/home/shirai/.gacc.csv",header=T,stringsAsFactors = F)[1,]
#認証を通す
ga$SetCredential(ac$mail,ac$pw)

コード(クエリー、集計、グラフ化)

クエリーを組み立てて、データ集計、グラフ化まで

#queryオブジェクトを作ってリクエストを作る。ビルドパターンって奴?
query <- QueryBuilder()
id <- "ga:21600568"
start.date = "2010-01-01"; end.date = "2010-12-30"
query$Init(start.date=start.date, end.date = end.date, table.id = id,
          dimensions = c("ga:date"),
          metrics = c("ga:visits,ga:pageviews,ga:timeOnSite"))

#データ取得 $dataにデータが、それ以外にはレコード数とかもある
output <- ga$GetReportData(query)
data.b <- output$data

#使い易いように、カラム名を加工、日付データは日付型に
names(data.b) <- sub("ga:","",names(data.b))
data.b$date <- as.Date(data.b$date, "%Y%m%d")

#滞在時間は平均滞在時間に、pageviewは平均PVへ、いるものだけ残す
data.b <- transform(data.b, avStay = (timeOnSite/visits))
data.b <- transform(data.b, avPV = (pageviews/visits))
data.b <- data.b[, c("date","visits","avStay","avPV")]

#ずるして、avPVは3000(5分)以上はNAに。 異常値なので
data.b$avStay <- ifelse(data.b$avStay > 1800, NA, data.b$avStay)

#パッケージのreshape機能。いわゆる?行持ちのデータ(日付 x データ種類 x 数値)に
data.b.molten <- melt(data.b, id="date")
head(data.b.molten) #ちょっと出力
#|       date | variable | value |
#| 2010-01-01 | visits   |     9 |
#| 2010-01-02 | visits   |     7 |
#| 2010-01-03 | visits   |     9 |
#| 2010-01-04 | visits   |    20 |
#| 2010-01-05 | visits   |    32 |
#| 2010-01-06 | visits   |    18 |
#
#ggplotで出力(x軸にdate,y軸にvalue:数値,
p <- qplot(date, value, data=data.b.molten, geom="line", main = "基本数値")

#ここで、グループ別に図示する機能 facet_gridを使う, 縦軸スケールは個別で
p <- p + facet_grid(variable ~ ., scale="free_y")

#見た目を調整して、ファイルに出力
p <- p + opts(axis.text.x = theme_text(size=5))
p <- p + opts(strip.text.x = theme_text(size=5))
p <- p + scale_x_date(major="1 month", format="%m月")
ggsave("basic.png", height=6, width=6, dpi=96)

結果

ぎざぎざ。データの把握がしにくいですね。

https://i1.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-basic.png?w=660&ssl=1

対策としては、週別のデータにすればいいけど、それだと一日の変動の様子が消えてしまう。下で移動平均を考えることによって、曜日変動の除去を考えるけど、ページ別のセッション数も見ておく。

ページ別セッション数の累計表示

  • 全ソースでのページ別
    query$Init(start.date=start.date, end.date = end.date, table.id = id,
               dimensions = c("ga:date,ga:pagePath"),
               metrics = c("ga:uniquePageviews"),
               max.results = 10000,
               start.index = 1
               )
    ret <- ga$GetReportData(query,max.rows=50000)
    pv.data <- ret$data
    names(pv.data) <- sub("ga:","",names(pv.data))
    pv.data$date <- as.Date(pv.data$date, "%Y%m%d")
    ret <- ddply(pv.data, .(pagePath), summarise, pagesum = sum(uniquePageviews))
    top5.urls <- ret[rev(order(ret[,"pagesum"]))[1:5],1]
    pv.data.top5 <- subset(pv.data, pagePath %in% top5.urls)

    上位5ページを表示

    p <- qplot(date, uniquePageviews, data=pv.data.top5, geom="line", log="y")
    p <- p + facet_grid(pagePath~., labeller = function(l,x)substr(x,0,30),scales='free_y')
    p + opts(strip.text.y = theme_text(angle=0)) + scale_x_date(major="1 month", format="%m")
    ggsave("visits.png", height=5, width=6,dpi=96)

    https://i2.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-visits.png?w=660&ssl=1

    累計で表示してみる

    pv.data.top5.cumsum <- ddply(pv.data.top5, .(pagePath), transform, cumsum = cumsum(uniquePageviews))
    p2 <- ggplot(data=pv.data.top5.cumsum, aes(date,cumsum,color=pagePath)) + geomline()
    p2 + opts(legend.position="bottom") + scalexdate(major="1 month", format="%m")
    p2 + opts(legend.position="bottom", legend.box="vertical")
    ggsave("cumsumvisits.png", height=5, width=6, dpi=96)
    

    https://i0.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-cumsum_visits.png?w=660&ssl=1

    積み上げのが比較しやすいのかも
    10月過ぎから勢いがついたページがある。

  • ソース別(yahoo,google)で見てみる。yahooとgoogleのセッション数を見てみる
    query$start.index(1)
    query$dimensions("ga:data,ga:pagePath,ga:source")
    ret <- ga$GetReportData(query,max.rows=50000)
    pv.data <- ret$data
    names(pv.data) <- sub("ga:","",names(pv.data))
    pv.data$date <- as.Date(pv.data$date, "%Y%m%d")
    pv.data.top5 <- subset(pv.data, pagePath %in% top5.urls)
    pv.data.top5.yg <- subset(pv.data.top5, source %in% c("yahoo","google"))
    pv.data.top5.yg.cumsum <- ddply(pv.data.top5.yg, .(pagePath), transform, cumsum = cumsum(uniquePageviews))
    p2 <- ggplot(data=pv.data.top5.cumsum, aes(date,cumsum,color=source)) + geom_line()
    p2 + facet_grid(pagePath~.,scale="free_y",labeller=function(l,x)substr(x,1,20)) + opts(strip.text.y = theme_text(angle=0))
    ggsave("upv_yg.png", width=5,height=5,dpi=96)

    https://i0.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-upv_yg.png?w=660&ssl=1

    あんまり関係なさそう。あとyahooから来るのは一ヶ月遅い(かった)。

期間効果(曜日)を考慮する

考え方

曜日効果を考慮することによって、日別の変動を捉えつつ、ギザギザ問題の解消を目指します。Rのdocompose関数を使って、曜日効果とトレンドを分離します。

基本のアイデアは、観測値を (季節分+トレンド+誤差) と考えて、7日間の移動平均をとれば、曜日効果はキャンセルアウトされる。
んで、誤差もキャンセルアウトとまずは考える。なので、移動平均はトレンドの値と考えられる。曜日効果分は、曜日ごとの平均を出して、全体の平均から引いて出す。
で、実測値から、トレンドと曜日分を引いたのが誤差分。

こんな考えらしい。細かくは曜日分や誤差分にトレンドを入れたりするみたいだけど、decompose関数は普通にそのまんまみたい。で、decompose関数でいきます。

まずはセッション数。

  • コード
    #前のデータをそのままで visitsのdecomposeする。tsオブジェクトにする
    #曜日効果なので、7日間を指定,日付に関しては無視
    visits.c <- ts(data.b$visits, freq=7)
    #decompose関数はそのまんま、入れるだけ
    visits.d <- decompose(visits.c)
    #ggplotで出力するので、data.frameに戻す
    visits.d1 <- as.data.frame(visits.d[c(2,1,3)])
    #NAが初めと終わりに3日づつでるので、除去
    visits.d2 <- visits.d1[c(-1,-2,-3,-362,-363,-364),]
    #日付を再代入
    visits.d2$date <- seq(as.Date("2010-01-04"),as.Date("2010-12-27"),by=1)
    #元データと合体して、列順を入れ替え
    visits.d2$observe <- data.b$visits[c(-1,-2,-3,-362,-363,-364)]
    visits.d2 <- visits.d2[, c(5,1,2,3,4)]
    #meltさせて行持ちにして、グラフ
    p <- qplot(date,value, data = melt.data.frame(visits.d2, id.vars="date"), geom="line")
    p + facet_grid(variable~., scales='free_y')
    ggsave("decompose.png", width=6, height=6, dpi=96)
  • 結果上から 実測値、トレンド、曜日効果分、誤差分https://i0.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-decompose.png?w=660&ssl=1セッション数の曜日別差異(合計は 0 )
    9.7 14.3 16.7 15.4 11.9 -32.8 -35.2 0.

    とりあえず、トレンドは見える感じです。
    週刊平均値をプロットするよりは、ダイナミック。日別よりは見やすい。

平均滞在時間も曜日効果を見る

エンゲージメントの測定として、滞在時間を対象にします

  • 注意GAはeventTrackの値も滞在時間のログとしてみてます。
    なので、eventTrackを細かく発行してると、通常よりは細かく滞在時間がでます。
    ただ、それでもこのサイトのeventTrackeの発行タイミングも等時間隔で出てるわけではないし、
    非常に怪しいデータではあります。
  • コード
    library(stringr)
    query$Init(start.date=start.date, end.date = end.date, table.id = id,
    dimensions = c("ga:date"),
    metrics = c("ga:visits,ga:pageviews,ga:timeOnSite"))
    d1 <- ga$GetReportData(query)
    d2 <- d1$data
    names(d2) <- str_replace(names(d2), "ga:", "")
    d2$date <- as.Date(d2$date,"%Y%m%d")
    d2 <- transform(d2, avTime = timeOnSite/visits)
    #4月以降のデータにする(1−3月は計測方法が違うので)
    d3 <- subset(d2, date >= as.Date("2010-04-01"))
    dc.avtime <- decompose(ts(d3$avTime, f=7))
    dc.visits <- decompose(ts(d3$visits, f=7))
    #曜日別の滞在時間(結果画面で)
    print(dc.visits$figure)
    print(dc.avtime$figure)
    #trendDataだけ持ってくる
    d.bind <- data.frame(
    visits = dc.visits$trend,
    avTime = dc.avtime$trend,
    date = seq(as.Date("2010-04-01"),as.Date("2010-12-30"),by=1))
    #平均化によるデータのない部分を除去
    d.bind2 <- d.bind[c(-1,-2,-3, -272,-273,-274),]
    #グラフ化
    p <- qplot(date,value, data=melt(d.bind2, id.var="date"),geom="line")
    p <- p + facet_grid(variable~.,scale="free_y")
    p <- p + scale_x_date(major="1 month", format="%m")
    p +  opts(ylab="上:セッション数 下:平均滞在時間(秒)
    ggsave("trend_visits_timeonsite.png",height=6,width=6,dpi=96)
  • 結果曜日別差異を見る
    セッション数(上にだしたと同じもの)
    9.7 14.3 16.7 15.4 11.9 -32.8 -35.2

    滞在時間(単位は秒数)

    月曜 火曜 水曜 木曜 金曜 土曜 日曜
    45.8 4.9 53.9 20.3 20.3 (-)46.0 (-)99.2

    トレンドデータ(曜日効果除去後のもの)

    https://i2.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-trend_visits_timeonsite.png?w=660&ssl=1なんかこれだけでは、よくわからんかも。 曜日別というより、他のセグメントを当たる必要がある。

分布を見る。滞在時間分布(セグメントデータとして)を見る

考え方

日別の集計値としての、平均滞在時間ではなんとも言いがたい。
実は、GAはセッション滞在時間もセグメント情報として持ってる。
なので、他のセグメント情報と掛け合わせで、滞在時間によるセッションの分布がだせる。
指標側では平均しか見えないけど、こちらは分布まで見える。
ここでは、月別とメディア別とランディングページ別を見てみる
ただ、上でも書きましたが、滞在時間データそのものの信頼性には疑問はあります。
僕自身のRの演習が主目的になっちゃってます。

月間別

月別のセグメントも入れて、データを取得。滞在時間は ga:visitLength

  • 単純にバー表示
    #クエリーを組み立てる。その前は、前のコードから続いてるものがある
    query$dimensions("ga:visitLength,ga:month")
    query$metrics("ga:visits")
    
    #前と同じくmax.rowsは10000に増やす
    output <- ga$GetReportData(query,max.rows=10000)
    output$total.result #=>5708
    d1 <- output$data
    names(d1) <- sub("ga:","",names(d1))
    
    #バープロットは、通常はcountデータをとるけど、weight指定で合計もいける
    p <- qplot(visitLength, data=d1, geom="bar", weight=visits, log="y")
    p + facet_grid(month~.)

    なんかみずらい、、、右側に月の表示。左側にセッション数、x軸は滞在時間だけど、、謎グラフになった。
    あと滞在時間が、飛び飛びになってるが怪しいし、0秒がどこだか不明だし、、
    全然だめ、、

    https://i1.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-bar_month_visits.png?w=660&ssl=1

    横軸を詰める。facet_wrapで表示。

    p <- qplot(visitLength, data=d1, geom="bar", weight=visits, log="xy")
    p + facet_wrap(~month)

    こちらのがみやすい。

    https://i2.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-month_stay_dst.png?w=660&ssl=1

  • density表示にするR(ggplot2)は、近似曲線も計算して引いてくれる。
    月別の分布を密度で近似線表示
    #http://tolstoy.newcastle.edu.au/R/e2/help/06/10/2836.html
    d2 <- data.frame(lapply(d1, rep, d1$visits)[1:2])
    d2$visitLength <- as.numeric(d2$visitLength)
    qplot(x=d2$visitLength, data=d2, geom="density",binwidth=10) + facet_grid(month ~ .)
    ggsave(dpi=96,width=6,height=6,file="hist_month_visits.png")

    https://i0.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-hist_month_visits.png?w=660&ssl=1

    なんか形は違ってきましたね、、、くらいか。

  • 平均値と中央値の表示
    これでも意味不明なので、平均値と中央値と引く
    近似線と実数(密度だけど)のバーを合わせて表示もする。
    #中央値と平均値を求める
    stt <- ddply(d2, .(month), function(x) data.frame(median=median(x$visitLength),
                                                       mean=mean(x$visitLength)))
    #以下、グラフ出力今回は、barplotとdensityを合わせる
    p <- ggplot(d2, aes(visitLength)) + geom_histogram(aes(y=..density..)) + geom_density()
    p <- p + facet_grid(month ~ ., labeller=function(l,x)paste(x,"月",sep=""))
    p <- p + opts(strip.text.y = theme_text(hjust=1, angle=0))
    p <- p + geom_vline(data=stt, aes(xintercept=stt$median), color=I("red"))
    p <- p + geom_vline(data=stt, aes(xintercept=stt$mean), color=I("green"))
    ggsave("hist_month_visits2.png",width=6,height=10,dpi=96)

    レジェンドが引けなかった、、、緑が平均値。赤が中央値。

    複数のgeomがある場合のlegendの対象指定はどうなのだろう?

    https://i1.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-hist_month_visits2.png?w=660&ssl=1

メディア別

時間変化とは別にメディア別もやってみる。

  • バープロット
    query$dimensions("ga:visitLength,ga:medium")
    query$metrics("ga:visits")
    output.m <- ga$GetReportData(query,max.rows=10000)
    d.m <- output.m$data
    colnames(d.m) <- sub("ga:","", colnames(d.m))
    #organic, referral, (none) に絞る
    d.m1 <- subset(d.m, medium %in% c("organic","referral","(none)"))
    #visits単位のレコードに
    d.m2 <- data.frame(lapply(d.m1[1:2], rep, d.m1$visits))
    d.m2$visitLength <- as.numeric(d.m2$visitLength)
    p <- ggplot(d.m2, aes(x=medium, y=visitLength)) + stat_boxplot()
    p <- p + coord_flip() + ylab("滞在時間(秒)")
    ggsave("boxplot_medium_visits.png",width=6,height=6,dpi=96)

    https://i2.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-boxplot_medium_visits.png?w=660&ssl=1

    分類が大まかすぎる。下でキーワード別をやる

  • 四分表示
    数値を出しておく
    今度は分表示にしておく。
    ddply(d.m2, .(medium), function(x) round(quantile(x$visitLength/60)))

    メディア別滞在時間分布(分)

    medium 0% 25% 50% 75% 100%
    (none) 0 2 12 22 33
    organic 0 6 16 24 33
    referral 0 4 14 23 33

月とメディア別でクロス

上で月別、メディア別をやったけど、両者を合わせる。

#組み合わせ
    query$dimensions("ga:visitLength,ga:medium,ga:month")
    query$metrics("ga:visits")
    output.mm <- ga$GetReportData(query,max.rows=100000)
    d.mm <- output.mm$data
    colnames(d.mm) <- sub("ga:","", colnames(d.mm))
    #organic, referral, (none) に絞る
    d.mm1 <- subset(d.mm, medium %in% c("organic","referral","(none)"))
    #visits単位のレコードに
    d.mm2 <- data.frame(lapply(d.mm1[1:3], rep, d.mm1$visits))
    d.mm2$visitLength <- as.numeric(d.mm2$visitLength)
    p <- ggplot(d.mm2, aes(x=medium, y=visitLength, color=medium)) + stat_boxplot()
    p <- p + facet_grid(.~month) + ylab("滞在時間(秒)")
    p <- p + opts(axis.text.x = theme_text(angle=90,hjust=0, vjust=0))
    ggsave("boxplot_medium_month_visits.png",width=8,height=5,dpi=96)

結果

https://i1.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-boxplot_medium_month_visits.png?w=660&ssl=1

数字も出しておく

母数(セッション数)

cast(d.mm2, medium~month,  length)
medium 04 05 06 07 08 09 10 11 11
(none) 139 117 337 199 217 309 256 229 161
organic 842 1007 1194 1541 1477 1453 1586 1713 1392
referral 124 79 506 182 354 392 231 218 172

滞在時間平均値

cast(d.mm2, medium~month,  function(x)round(mean))
medium 04 05 06 07 08 09 10 11 12
(none) 671 723 722 903 741 702 822 813 962
organic 682 794 912 942 909 914 956 952 967
referral 590 780 800 892 860 832 867 973 1009

滞在時間中央値

cast(d.mm2, medium~month,  function(x)round(median))
medium 04 05 06 07 08 09 10 11 12
(none) 552 686 704 960 703 661 772 778 1022
organic 609 745 1002 1022 948 975 1016 1002 1002
referral 183 882 826 917 874 833 778 1002 1056

キーワード + ランディングページ別のセッション滞在時間

ここからは、キーワードを見ていく。指標はそのまま滞在時間。

ドット表示 + ファセット(ランディングページ)

ランディングページもセグメントに加えてみる。

##dimensionとmetricsを設定して取得。他の項目はそのまま
query$dimensions("ga:landingPagePath,ga:visitLength,ga:keyword")
guery$metrics("ga:entrances")
#前回のindexがclearされないみたい。1に戻しておく。
query$start.index(1)
out.k <- ga$GetReportData(query,max.rows=100000)
str(out.k)

得られるデータはこんな感じ
閲覧開始は15379回あった。レコード?数は13061

List of 3
 $ data         :'data.frame':  13061 obs. of  4 variables:
  ..$ ga:landingPagePath: chr [1:13061] "/" "/" "/" "/" ...
  ..$ ga:visitLength    : chr [1:13061] "0" "0" "0" "0" ...
  ..$ ga:keyword        : chr [1:13061] "(not set)" "abc-analytics.com" "analytcs.com" "analytics tracking code input" ...
  ..$ ga:entrances      : num [1:13061] 96 1 1 1 1 3 1 1 2 1 ...
 $ aggr.totals  :'data.frame':  1 obs. of  1 variable:
  ..$ aggregate.totals: num 15379
 $ total.results: num 13061

 

d.k <- out.k$data
names(d.k) <- sub("ga:","",names(d.k))
d.k1 <- data.frame(lapply(d.k[1:3], rep, d.k$entrances))
str(d.k1)

こんな形のデータになる。閲覧開始数は消えて1セッション=1レコードの形に。(本当は開始数=セッションではないが)

data.frame’: 15379 obs. of 3 variables:
$ landingPagePath: Factor w/ 525 levels “/”,”%EE3%81%97%E3%81%9F”,..: 1 1 1 1 1 1 1 1 1 1 … $ visitLength : Factor w 1893 levels “0”,”1″,”10″,”100″,..: 1 1 1 1 1 1 1 1 1 1 …
$ keyword : Factor w/ 6904 levels “”/nan” アナリティクス”,..: 57 57 57 57 57 57 57 57 57 57 …

とりあえず、閲覧開始上位5ページに対象を絞る

top5.pages <- names(rev(sort(d.k1$landingPagePath))[1:5])
d.k2 <- subset(d.k1, landingPagePath %in% top5.pages)
#使わないファクターをdrop
d.k2 <- droplevels(d.k2)

上位30キーワードにデータをさらに絞る

top30.kw <- names(rev(sort(table(d.k2$keyword)))[1:30])
d.k3 <- subset(d.k2, keyword %in% top30.kw)
d.k3$visitLength <- as.numeric(d.k3$visitLength)
d.k3 <- droplevels(d.k3)
str(d.k3)

こんな感じのデータソースになる 3347セッション,5ページの30キーワードについて,811通りの滞在時間

‘data.frame’: 3347 obs. of 3 variables:
$ landingPagePath: Factor w/ 5 levels “/”,”/measurehowmuchviewedingoogleanalytics“,..: 1 1 1 1 1 1 1 1 1 1 …
$ visitLength : num 1 1 1 1 1 1 1 1 1 1 …
$ keyword : Factor w/ 30 levels “(not set)”,”analytics tracking code input”,..: 1 1 1 1 1 1 1 1 1 1 …

グラフ化。透明度を半分にして、重なり表示

p <- qplot(data=d.k1, x=visitLength,y=KW1, alpha=I(1/2))
p <- p + facet_grid(LP1 ~ ., scales="free_y", space="free",labeller=function(l,x){substr(x,1,20)})
p <- p + coord_trans(x="log10")
p <- p + opts(strip.text.y = theme_text(angle=0))
p
ggsave(filename="landing_keyword_length.png", width=10, height=10, dpi=96)

https://i1.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-landing_keyword_length.png?w=660&ssl=1

似たようなキーワードを統合して扱わないとキーワード別にしても意味なさそう
なので、キーワードグルーピングをやる

キーワードグループ別滞在時間

さて、キーワードはバラバラになりすぎてて、全体の把握が難しい。
キーワードでは検索フレーズ単位で管理されているので、同じ意味でもたくさんの項目になってるせい。統合しないといけないのだが、やり方不明、、、

  • キーワードに分解して整理する空白のものを単語に分解して整理してみる。
    上で、1セッション1レコードの形でキーワードが含まれる形を作ったので、それを使う。
    #(not set)を除く
    d.k2 <- subset(d.k1, keyword != "(not set)")
    #キーワードを" "区切りで文字ベクトルにする
    k1 <- sapply(as.character(d.k2$keyword), function(x) str_split(x," "))
    length(k1)
    [1] 11406
    #検索キーワードア辺り、平均2.7くらいの語数か
    R> sum(sapply(k1, length))
    [1] 28921
    #2,3語くらいが多い
    table(sapply(k1, length))

    検索フレーズでの単語数

    1語 2語 3語 4語 5語 6語 7語 8語 9語 10語
    2138 3646 3603 1568 333 98 10 5 3 2

    単語単位で見る

    #これをベクトルにする loop以外に思いつかない、、、
    ret <- ""
    for(i in 1:length(k1)) ret <- c(ret,k1[[i]])
    #よくわかってないけど、この形が便利そう
    k.table <- adply(rev(sort(table(ret))), 1, function(x)x)
    names(k.table) <- c("kw","cumsum")
    #上位10単語を出力
    k.table[1:10,]

    単語単位で見るキーワード登場回数(単語別での累計セッション数)のベスト10

    1 google 3876
    2 analytics 3748
    3 アナリティクス 482
    4 アクセス解析 482
    5 googleanalytics 463
    6 ユニークユーザー 413
    7 ページ別セッション数 347
    8 cookie 297
    9 セッション 277
    10 api 270

    とりあえず、整理しやすい単位に分解はできた。

  • 同時出現表を作る分解したあとは、どういう組み合わせになっていたかを表示する。
    同時に使われていた単語を集計する
    先頭の10単語について、同時に使われた単語の出現回数を数える
    library(string r)
    #整理
    d.k1 <- d.k1[, c(-4,-5)]
    #googleといっしょに検索された言葉
    d.k.google <- d.k1[grep("google", d.k1$keyword),"keyword"]
    d.k.google2 <- Reduce(c, str_split(d.k.google, " "), ac=F)

    google という単語と一緒に検索された単語

    google 325
    analytics 262
    ユニークユーザー 99
    閲覧開始ページ 60
    アクセス解析 38
    ユニークユーザー数 32
    an 25
    ページ別セッション数 21
    ユニークユーザ 21
    アナリティクス 17
    googleanalytics 16
    sql 16
    使う 16
    見方 15
    閲覧開始 14

    他の単語にも適用する 上位8単語にする

    ret <- sapply(top10, function(word, df){
                            kws <- df[grep(word, df$keyword),"keyword"]
                            Reduce(c, str_split(kws," "), ac=F)
                         }
                  , d.k1)
    ret.top8 <- ldply(ret, function(x){
                             d <- sort(table(x),d=T)[1:8]
                             mapply(paste,sep=":", d, names(d))
                            })
    #各単語ごとに、同時出現単語を上位8個抽出
    out <- ldply(ret, function(x) sort(table(x),d=F)
    #タテヨコ逆転
    t(out)

    検索フレーズに含まれたもの(冒頭の数字が出現回数)*最初は同じ単語なので、その単語のキーワード回数

    “google” “analytics” “アナリティクス” “アクセス解析” “googleanalytics”
    “3876:google” “3748:analytics” “482:アナリティクス” “482:アクセス解析” “463:googleanalytics”
    “2549:analytics” “2577:google” “235:google” “148:google” “26:閲覧開始ページ”
    “463:googleanalytics” “463:googleanalytics” “74:googleアナリティクス” “53:analytics” “21:ユニークユーザー”
    “236:アナリティクス” “191:ユニークユーザー” “51:ユニークユーザー” “33:セッション” “15:ページ別”
    “218:ユニークユーザー” “168:api” “43:グーグルアナリティクス” “17:api” “15:目標到達プロセス”
    “202:api” “121:閲覧開始ページ” “24:閲覧開始ページ” “16:ユニークユーザー” “14:複数ドメイン”
    “153:アクセス解析” “107:セッション数” “21:ページ別セッション” “12:グーグル” “13:カスタム変数”
    “117:apps” “95:セッション” “18:ページ別” “12:外部リンク” “12:セッション”

    内訳はこんな感じ。眺めるだけ、、middle wordでやればと想うけど、、、

  • グループ化してグラフにこの10単語でグルーピングする
    重複所属は、どちらにもカウントするようにする
    #ごちゃごちゃしてきたけど、、、グループ名カラムを追加して、dataframeを作り直し
    d.g <-  do.call("rbind",lapply(top10, function(group) cbind(d.k1[grep(group,d.k1$keyword),],group)))
    ddply(d.g, .(group), function(df)each(median,mean,length)(df$visitLength))

    キーワードグループごとの、中央値、平均値、lengthはセッション数

    group median mean length
    google 905.0 871.9 4668
    analytics 904.0 867.8 4487
    アナリティクス 904.5 874.3 614
    アクセス解析 904.0 869.9 545
    googleanalytics 953.0 903.5 474
    ユニークユーザー 928.0 903.5 632
    ページ別セッション数 928.0 923.1 405
    cookie 977.0 919.7 326
    セッション 964.0 911.6 1369
    api 973.0 915.8 285

    滞在が10秒で、Yes or No

    ddply(d.g, .(group), function(df)table(df$visitLength<10))

    FALSEが10秒以上滞在セッション数

    group FALSE TRUE
    google 4182 486
    analytics 4018 469
    アナリティクス 541 73
    アクセス解析 483 62
    googleanalytics 425 49
    ユニークユーザー 591 41
    ページ別セッション数 390 15
    cookie 296 30
    セッション 1271 98
    api 252 33

    グラフ描画(分布点と四分点表示プロットを合わせる)

    p <- qplot(data=d.g, y=visitLength,x=group,alpha=I(1/10)) + geom_jitter()
    p +  geom_boxplot(alpha=I(1/3), color=I("red"))+ ylab("滞在時間(秒)") + xlab("キーワードグループ")
    p +  coord_flip()
    ggsave(filename="landing_grouped_keyword_length.png", width=6, height=6, dpi=96)

    結果
    https://i0.wp.com/abc-analytics.com/wp-content/uploads/2011/01/wpid-landing_grouped_keyword_length.png?w=660&ssl=1