Guess-js という、Google Analytics のデータを元に、ページの先読みを行う、興味深いライブラリがあります。
guess-js/guess: Libraries & tools for enabling Machine Learning driven user-experiences on the webREADME.mdに、以下のような記載があります。

Another approach that could be taken (which is simpler) is attempting to get accurate prediction data from the Google Analytics API. If you ran a report for the Page and Previous Page Path dimension combined with the Pageviews and Exits metrics this should provide enough data to wire up prefetches for most popular pages.

メトリクス ga:pageviews、ga:exits と、 ディメンション ga:pagePath、ga:previousPagePath を取得したレポートの情報で、
ページの先読みに必要な情報は事足りていそうで、実際 guess-js の先読みデータはこのデータが使われています。
このレポートのメトリクス、ディメンションを参考にして、Python でデータを取得して、同じようなデータを作れないか試してみました。
以下、実施したことを記載します。


前提

  • OS

    % sw_vers
    ProductName:  Mac OS X
    ProductVersion: 10.13.6
    BuildVersion: 17G3025
    

  • Python の Version

    % python3 -V
    Python 3.6.5
    

  • 必要なライブラリ
    GoogleAnalytics のデータ取得には、Google2Pandas を使用しています。
    Google2Pandas の使い方は以下記事で説明していますので、よろしければご確認ください。
    Google2Pandas で、Google Analytics のデータを pandas Dataframe に変換する | Monotalk
    また、あまりちゃんと記載をちゃんとしていないですが、API 認証 は サービスアカウントでの認証を行っています。
    以下の記事にサービスアカウントの作成手順が記載されていますので、アカウントがない場合はご確認ください。
    初心者でも分かる!なGoogle Analytics APIの使い方

レポートの取得

メトリクス ga:pageviews、ga:exits と、 ディメンション ga:pagePath、ga:previousPagePath を指定し、データを取得します。

データフレームの取得

条件を指定して、データフレームを取得します。

from google2pandas import *
view_id = 'YOUR_VIEW_ID'
query = {
    'reportRequests': [{
        'viewId' : view_id,
        'dateRanges': [{
            'startDate' : '180daysAgo',
            'endDate'   : 'today'}],
        'dimensions' : [
            {'name' : 'ga:pagePath'}, 
            {'name' : 'ga:previousPagePath'},
        ],
        'metrics'   : [
            {'expression' : 'ga:pageviews'},
            {'expression' : 'ga:exits'},
        ],
    }]
}
conn = GoogleAnalyticsQueryV4(secrets='./ga_client.json')
df = conn.execute_query(query)
df
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
pagePath previousPagePath pageviews exits
0 / (entrance) 1009 753
1 / / 141 56
2 / /?page=18 1 0
3 / /?page=2 6 1
4 / /about/ 28 8
5 / /amp/blog/amp-start-の-blog-テーマは内部でどんなcss-を使ってい... 1 1
6 / /amp/blog/Continuing-technical-blogging-with-V... 2 2
7 / /amp/blog/django-rest-framework-でserializer-をネ... 1 0
8 / /amp/blog/github-page-を-gatsby-で構築する/ 1 0
9 / /amp/blog/google-モバイルサイト認定を取得してみました/?__twitter... 1 1
10 / /blog/AB-test-tool-Web-personalization-tool-RT... 2 0
11 / /blog/About-statistical-information-of-blog-po... 4 1
12 / /blog/Add-bat-bot-of-ultimate-bad-bot-blocker-... 2 1
13 / /blog/amp-roadshow-tokyo-2018-に参加しました/ 2 0
14 / /blog/amp-の-update-cache-要求を-apikeypub-を使用して送っ... 1 1
15 / /blog/apache-wicketでrestapiを使う/ 1 0
16 / /blog/args4j-で-enumoptionhandler-を使う/ 1 0
17 / /blog/at-comfasterxmljacksondatabindexcunrecog... 2 0
18 / /blog/author/monotalk/?page=19 1 1
19 / /blog/Block-multiple-requests-of-Wicket-Ajax/ 1 1
20 / /blog/Calculate-coefficient-of-variation-with-... 5 1
21 / /blog/Calculate-hypergeometric-distribution-wi... 1 1
22 / /blog/Calculate-inequality-index-in-python/ 2 1
23 / /blog/Calculate-polynomial-regression-with-pyt... 4 0
24 / /blog/Calculate-the-F-distribution-with-python/ 2 0
25 / /blog/Calculate-the-interquartile-range-with-p... 1 1
26 / /blog/Calculate-the-previous-term-growth-rate-... 5 0
27 / /blog/Calculate-the-probability-of-binomial-di... 2 1
28 / /blog/Calculate-uniform-distribution-in-Python/ 2 1
29 / /blog/category/google-tag-manager/ 1 1
... ... ... ... ...
4516 /translate_c?depth=1&hl=en&prev=search&rurl=tr... /translate_c?depth=1&hl=en&prev=search&rurl=tr... 1 1
4517 /translate_c?depth=1&hl=en&prev=search&rurl=tr... (entrance) 1 1
4518 /translate_c?depth=1&hl=en&prev=search&rurl=tr... (entrance) 1 1
4519 /translate_c?depth=1&hl=en&prev=search&rurl=tr... (entrance) 2 2
4520 /translate_c?depth=1&hl=en&prev=search&rurl=tr... (entrance) 1 1
4521 /translate_c?depth=1&hl=en&prev=search&rurl=tr... (entrance) 1 1
4522 /translate_c?depth=1&hl=en&prev=search&rurl=tr... (entrance) 1 1
4523 /translate_c?depth=1&hl=en&rurl=translate.goog... (entrance) 1 1
4524 /translate_c?depth=1&hl=en&rurl=translate.goog... (entrance) 1 1
4525 /translate_c?depth=1&hl=en&rurl=translate.goog... (entrance) 1 1
4526 /translate_c?depth=1&hl=es&prev=search&rurl=tr... (entrance) 1 0
4527 /translate_c?depth=1&hl=es&prev=search&rurl=tr... /translate_c?depth=1&hl=es&prev=search&rurl=tr... 1 1
4528 /translate_c?depth=1&hl=es&prev=search&rurl=tr... (entrance) 1 1
4529 /translate_c?depth=1&hl=es&prev=search&rurl=tr... (entrance) 1 1
4530 /translate_c?depth=1&hl=fr&prev=search&rurl=tr... (entrance) 1 1
4531 /translate_c?depth=1&hl=hu&prev=search&rurl=tr... (entrance) 1 1
4532 /translate_c?depth=1&hl=ja&ie=UTF8&prev=_t&rur... (entrance) 1 1
4533 /translate_c?depth=1&hl=ko&prev=search&rurl=tr... (entrance) 1 1
4534 /translate_c?depth=1&hl=ko&prev=search&rurl=tr... (entrance) 1 0
4535 /translate_c?depth=1&hl=ko&prev=search&rurl=tr... (entrance) 1 1
4536 /translate_c?depth=1&hl=ko&prev=search&rurl=tr... (entrance) 1 1
4537 /translate_c?depth=1&hl=ko&rurl=translate.goog... /translate_c?anno=2&depth=1&hl=ko&rurl=transla... 1 1
4538 /translate_c?depth=1&hl=pt-BR&prev=search&rurl... (entrance) 1 1
4539 /translate_c?depth=1&hl=te&nv=1&prev=search&ru... (entrance) 1 1
4540 /translate_c?depth=1&hl=zh-CN&prev=search&rurl... (entrance) 1 1
4541 /translate_c?depth=1&hl=zh-CN&prev=search&rurl... (entrance) 1 0
4542 /translate_c?depth=1&hl=zh-CN&prev=search&rurl... /translate_c?depth=1&hl=zh-CN&prev=search&rurl... 1 0
4543 /translate_c?depth=1&hl=zh-CN&prev=search&rurl... (entrance) 1 1
4544 /translate_c?depth=1&hl=zh-CN&rurl=translate.g... /translate_c?anno=2&depth=1&hl=zh-CN&rurl=tran... 1 0
4545 /translate_c?depth=1&hl=zh-TW&prev=search&rurl... (entrance) 1 1

4546 rows × 4 columns

基本統計量の算出

データが多すぎてよくわからないので、基本統計量を算出します。

# 型変換
import numpy as np
df['exits'] = df['exits'].astype(np.int64)
df['pageviews'] = df['pageviews'].astype(np.int64)
df.describe()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
pageviews exits
count 4546.000000 4546.000000
mean 29.205235 24.223053
std 149.843488 130.766785
min 1.000000 0.000000
25% 1.000000 0.000000
50% 1.000000 1.000000
75% 5.000000 4.000000
max 4970.000000 4403.000000

基本統計量と、各属性値の関係から読み取れること

当たり前の話ですが基本統計量と、属性値から以下のことが読み取れるかと思います。

  • 50%以上の pageview数は1
  • 50%以上の 離脱数は1
  • previousPagePath が (entrance) は、前のページがないことを意味する。 ※ pagePath が流入ページになっている。
  • exits < pageviews となるのは、対象の pagePath から次のページへ移動した人がいるため。

データの加工

次ページの予測という観点で、以下のデータは除外してよいかと思いました。

  • previousPagePath が (entrance) のデータ
  • pageViewがある閾値に満たないデータ ※先読みをしても恩恵を受けられる人が少ないための足切り

まず、previousPagePath が (entrance) のデータを除外します。

# previousPagePath が `(entrance)` のデータを除外
df_excluded_entrance = df[df['previousPagePath'] != '(entrance)']
df_excluded_entrance
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
pagePath previousPagePath pageviews exits
1 / / 141 56
2 / /?page=18 1 0
3 / /?page=2 6 1
4 / /about/ 28 8
5 / /amp/blog/amp-start-の-blog-テーマは内部でどんなcss-を使ってい... 1 1
6 / /amp/blog/Continuing-technical-blogging-with-V... 2 2
7 / /amp/blog/django-rest-framework-でserializer-をネ... 1 0
8 / /amp/blog/github-page-を-gatsby-で構築する/ 1 0
9 / /amp/blog/google-モバイルサイト認定を取得してみました/?__twitter... 1 1
10 / /blog/AB-test-tool-Web-personalization-tool-RT... 2 0
11 / /blog/About-statistical-information-of-blog-po... 4 1
12 / /blog/Add-bat-bot-of-ultimate-bad-bot-blocker-... 2 1
13 / /blog/amp-roadshow-tokyo-2018-に参加しました/ 2 0
14 / /blog/amp-の-update-cache-要求を-apikeypub-を使用して送っ... 1 1
15 / /blog/apache-wicketでrestapiを使う/ 1 0
16 / /blog/args4j-で-enumoptionhandler-を使う/ 1 0
17 / /blog/at-comfasterxmljacksondatabindexcunrecog... 2 0
18 / /blog/author/monotalk/?page=19 1 1
19 / /blog/Block-multiple-requests-of-Wicket-Ajax/ 1 1
20 / /blog/Calculate-coefficient-of-variation-with-... 5 1
21 / /blog/Calculate-hypergeometric-distribution-wi... 1 1
22 / /blog/Calculate-inequality-index-in-python/ 2 1
23 / /blog/Calculate-polynomial-regression-with-pyt... 4 0
24 / /blog/Calculate-the-F-distribution-with-python/ 2 0
25 / /blog/Calculate-the-interquartile-range-with-p... 1 1
26 / /blog/Calculate-the-previous-term-growth-rate-... 5 0
27 / /blog/Calculate-the-probability-of-binomial-di... 2 1
28 / /blog/Calculate-uniform-distribution-in-Python/ 2 1
29 / /blog/category/google-tag-manager/ 1 1
30 / /blog/category/java/ 1 0
... ... ... ... ...
4477 /statistics/ /blog/Draw-a-correlogram-with-statsmodels/ 2 0
4478 /statistics/ /blog/Draw-a-stem-leaf-diagram-with-python-ste... 1 0
4479 /statistics/ /blog/Find-Bayesian-confidence-intervals-in-sc... 1 0
4480 /statistics/ /blog/How-to-use-the-sort-method-of-Google-App... 1 1
4481 /statistics/ /blog/mezzanine-blogに/ 1 1
4482 /statistics/ /blog/mezzanine-フロクの記事公開日の日付フォーマットを変更する/ 1 0
4483 /statistics/ /blog/Perform-independence-test-and-calculatio... 1 0
4484 /statistics/ /blog/Predict-future-impressions-with-Google-S... 1 1
4485 /statistics/ /blog/Python-implements-statistical-test-metho... 1 1
4486 /statistics/ /blog/pythonでポアソン分布の計算をする/ 4 1
4487 /statistics/ /blog/sonarqube-nodejs-に依存しないfrontend-lint-環境を... 1 0
4488 /statistics/ /blog/usage-of-django-compress-on-mezzanine/ 1 0
4489 /statistics/ /blog/wagtail-markdown-field-を使ってみる/ 1 0
4490 /statistics/ /categories/ 16 6
4491 /statistics/ /ja/staistics/ 2 2
4492 /statistics/ /search/?q=&type=blog.BlogPost 1 0
4493 /statistics/ /statistics/ 13 4
4494 /translate_c?act=url&depth=1&hl=en&ie=UTF8&pre... /translate_c?act=url&depth=1&hl=en&ie=UTF8&pre... 1 1
4495 /translate_c?act=url&depth=1&hl=en&ie=UTF8&pre... /translate_c?act=url&depth=1&hl=en&ie=UTF8&pre... 1 0
4498 /translate_c?act=url&depth=1&hl=en&ie=UTF8&pre... /translate_c?act=url&depth=1&hl=en&ie=UTF8&pre... 1 1
4501 /translate_c?anno=2&depth=1&hl=en&rurl=transla... /translate_c?depth=1&hl=en&prev=search&rurl=tr... 1 1
4504 /translate_c?anno=2&depth=1&hl=ko&nv=1&rurl=tr... /translate_c?anno=2&depth=1&hl=ko&nv=1&rurl=tr... 1 1
4506 /translate_c?anno=2&depth=1&hl=ko&rurl=transla... /translate_c?depth=1&hl=ko&prev=search&rurl=tr... 1 1
4508 /translate_c?anno=2&depth=1&hl=zh-CN&rurl=tran... /translate_c?depth=1&hl=zh-CN&prev=search&rurl... 1 0
4509 /translate_c?anno=2&depth=1&hl=zh-CN&rurl=tran... /translate_c?depth=1&hl=zh-CN&rurl=translate.g... 1 1
4516 /translate_c?depth=1&hl=en&prev=search&rurl=tr... /translate_c?depth=1&hl=en&prev=search&rurl=tr... 1 1
4527 /translate_c?depth=1&hl=es&prev=search&rurl=tr... /translate_c?depth=1&hl=es&prev=search&rurl=tr... 1 1
4537 /translate_c?depth=1&hl=ko&rurl=translate.goog... /translate_c?anno=2&depth=1&hl=ko&rurl=transla... 1 1
4542 /translate_c?depth=1&hl=zh-CN&prev=search&rurl... /translate_c?depth=1&hl=zh-CN&prev=search&rurl... 1 0
4544 /translate_c?depth=1&hl=zh-CN&rurl=translate.g... /translate_c?anno=2&depth=1&hl=zh-CN&rurl=tran... 1 0

3455 rows × 4 columns

再度、基本統計量を計算します。

df_excluded_entrance.describe()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
pageviews exits
count 3455.000000 3455.000000
mean 6.472648 4.223444
std 26.578358 19.022794
min 1.000000 0.000000
25% 1.000000 0.000000
50% 1.000000 1.000000
75% 2.000000 1.000000
max 674.000000 538.000000

続いて、pageViewがある閾値に満たないデータを除外します。
pandas で、previousPagePath で groupby して、previousPagePath ごとの pageview の合計を算出します。

df_groupby_pagepath = df_excluded_entrance.groupby('previousPagePath').sum()
df_groupby_pagepath
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
pageviews exits
previousPagePath
/ 641 254
/?page= 2 2 0
/?page= 3 1 0
/?page= 4 1 1
/?page=1 5 1
/?page=10 1 0
/?page=11 2 0
/?page=12 1 0
/?page=13 3 0
/?page=14 1 0
/?page=15 2 1
/?page=16 1 0
/?page=17 1 0
/?page=18 1 0
/?page=2 53 12
/?page=3 17 5
/?page=4 11 4
/?page=5 11 3
/?page=6 4 1
/?page=7 4 0
/?page=8 2 1
/?page=9 2 0
/about/ 91 34
/amp/blog/ 1 0
/amp/blog/404_errorpage_configration_on_wicket_dropwizard/ 1 1
/amp/blog/AB-test-tool-Web-personalization-tool-RTP-Website-Optimization/ 2 1
/amp/blog/About-formulas-in-Google-Spreadsheet-for-calculating-basic-statistics/ 6 5
/amp/blog/About-searching-and-completing-a-string-in-Google-Spread-Sheet/ 1 1
/amp/blog/About-statistical-information-of-blog-posts-recorded-as-custom-dimensions-and-events/ 7 1
/amp/blog/Calculate-coefficient-of-variation-with-python-scipy-and-numpy/ 6 3
... ... ...
/search/?q=標準得点+変動係数&type= 1 0
/search/?q=正規分布&type= 1 1
/search/?q=目次&type= 1 1
/search/?q=移動平均&type= 2 0
/search/?q=統計情報&type= 1 0
/search/?q=統計量&type= 1 0
/search/?q=継承&type= 2 0
/search/?q=著者&type= 1 0
/search/?q=項分布&type= 2 0
/search?q=cache:6Hj2PNT7p_IJ:https://www.monotalk.xyz/blog/elasticsearch-の-kuromoji-plugin-が削除されてindexclosedexceptionが発生する/+&cd=1&hl=ja&ct=clnk&gl=jp 1 1
/search?q=cache:AtYTm8CqpCIJ:https://www.monotalk.xyz/blog/cent-os-69-に-memcached-をインストールログの設定まで実施する/+&cd=1&hl=ja&ct=clnk&gl=jp 1 1
/search?q=cache:R029jladBYkJ:https://www.monotalk.xyz/blog/beautifulsoup-て-style-タクscript-タクstyle-属性を除去する/+&cd=8&hl=ja&ct=clnk&gl=jp 1 1
/search?q=cache:bdtGTPNBilkJ:https://www.monotalk.xyz/blog/bootstraps-javascript-requires-jquery-version-191-エラーについて/+&cd=1&hl=ja&ct=clnk&gl=jp 4 1
/search?q=cache:https://www.monotalk.xyz/blog/pythonで相関係数の計算をする/&rlz=1C1GCEU_jaJP821JP821&oq=cache:https://www.monotalk.xyz/blog/pythonで相関係数の計算をする/&aqs=chrome..69i57j69i58.959j0j4&sourceid=chrome&ie=UTF-8 1 1
/search?q=cache:lH1xzlsJJLQJ:https://www.monotalk.xyz/blog/content-security-policy-適用後の経過を観察する-2017年11月/+&cd=7&hl=ja&ct=clnk&gl=jp&client=firefox-b 1 1
/search?q=cache:tiQbVsjpKwsJ:https://www.monotalk.xyz/blog/django-runserver-実行時にログを全部出しする/+&cd=3&hl=ja&ct=clnk&gl=jp 1 1
/staistics/ 2 2
/statistics/ 66 10
/translate_c?act=url&depth=1&hl=en&ie=UTF8&prev=_t&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://www.monotalk.xyz/&xid=17259,15700023,15700124,15700149,15700168,15700186,15700191,15700201,15700208&usg=ALkJrhjtOYOh8APBIMaYgzAUfYz7hDqWHA 1 1
/translate_c?act=url&depth=1&hl=en&ie=UTF8&prev=_t&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://www.monotalk.xyz/blog/Draw-a-boxplot-with-data from-Google-Search-Console/&xid=17259,15700023,15700124,15700149,15700168,15700186,15700191,15700201,15700208&usg=ALkJrhj0yJX0Khr0Rv31gEvlN8iAql4H-w 1 0
/translate_c?act=url&depth=1&hl=en&ie=UTF8&prev=_t&rurl=translate.google.com&sl=auto&sp=nmt4&tl=fr&u=https://www.monotalk.xyz/blog/Error-A-partial-update-is-not-possible-for-a-component-that-has-renderBodyOnly-enabled-on-Wicket/&xid=17259,15700023,15700043,15700124,15700149,15700168,15700173,15700186,15700190,15700201&usg=ALkJrhi-6s44aa2jCIG84k0JJU58sEABOA 1 1
/translate_c?anno=2&depth=1&hl=ko&nv=1&rurl=translate.google.co.kr&sl=ja&sp=nmt4&tl=ko&u=https://www.monotalk.xyz/blog/sitespeedio-の-coach-を使って-webページのパフォーマンスを評価する/&xid=25657,15700022,15700122,15700124,15700149,15700168,15700186,15700190,15700201,15700208&usg=ALkJrhhUks2_n920PQOioH83LWYNTzJmuQ 1 1
/translate_c?anno=2&depth=1&hl=ko&rurl=translate.google.co.kr&sl=ja&sp=nmt4&tl=ko&u=https://www.monotalk.xyz/blog/sitespeedio-の-coach-を使って-webページのパフォーマンスを評価する/&xid=17259,15700002,15700023,15700124,15700149,15700168,15700186,15700190,15700201,15700208&usg=ALkJrhgMhHmycL10zo9Z4Wmm-gap-B80jQ 1 1
/translate_c?anno=2&depth=1&hl=zh-CN&rurl=translate.google.com.hk&sl=ja&sp=nmt4&tl=zh-CN&u=https://www.monotalk.xyz/blog/google-analytics-v4-api-java-pageview-per-url/&xid=17259,15700023,15700124,15700149,15700186,15700190,15700201&usg=ALkJrhh31NVtSiKXSwz4dLCXo80kP3JyMA 1 0
/translate_c?depth=1&hl=en&prev=search&rurl=translate.google.co.jp&sl=ja&sp=nmt4&u=https://www.monotalk.xyz/blog/google-app-script-の-urlfetchapp-の-例外ハンドリングについて/&xid=17259,1500004,15700019,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjyOtARNK8ZqludO98LMoYLY0SEGg 1 1
/translate_c?depth=1&hl=en&prev=search&rurl=translate.google.co.jp&sl=ja&sp=nmt4&u=https://www.monotalk.xyz/blog/検索キーワードの共起ネットワーク図を-cytoscape-で描画する/&xid=17259,15700023,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjmF9M06IEYQoCF3xAvbcUOJvGwbw 1 1
/translate_c?depth=1&hl=es&prev=search&rurl=translate.google.com.mx&sl=ja&sp=nmt4&u=https://www.monotalk.xyz/blog/uses-a-non-entity-orgeclipsepersistenceexceptionsvalidationexception/&xid=17259,15700022,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhhKlkTy_PBGLPcBDW0qrLjG4VV_bg 1 1
/translate_c?depth=1&hl=ko&prev=search&rurl=translate.google.co.kr&sl=ja&sp=nmt4&u=https://www.monotalk.xyz/blog/sitespeedio-の-coach-を使って-webページのパフォーマンスを評価する/&xid=17259,15700019,15700124,15700149,15700168,15700186,15700191,15700201,15700208&usg=ALkJrhhjVd65VmIk-4SEPx_4rg1QM0zYyA 1 1
/translate_c?depth=1&hl=zh-CN&prev=search&rurl=translate.google.com.hk&sl=ja&sp=nmt4&u=https://www.monotalk.xyz/blog/google-analytics-v4-api-java-pageview-per-url/&xid=17259,15700023,15700124,15700149,15700186,15700190,15700201&usg=ALkJrhgCFfDlxZvmrkmM26kKrdPhJ2ertQ 2 0
/translate_c?depth=1&hl=zh-CN&rurl=translate.google.com.hk&sl=ja&sp=nmt4&tl=zh-CN&u=https://www.monotalk.xyz/blog/google-analytics-v4-api-java-pageview-per-url/&xid=17259,15700023,15700124,15700149,15700186,15700190,15700201&usg=ALkJrhgiPDNYKGwelQJoT8KHqsIkYRUY_w 1 1

929 rows × 2 columns

基本統計量を算出します。

df_groupby_pagepath.describe()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
pageviews exits
count 929.000000 929.000000
mean 24.072121 15.707212
std 62.866513 41.896814
min 1.000000 0.000000
25% 1.000000 1.000000
50% 5.000000 2.000000
75% 19.000000 12.000000
max 707.000000 559.000000

ヒストグラムを描画してみます。

%matplotlib inline
ax = df_groupby_pagepath.plot(y='exits', bins=50, alpha=0.5, figsize=(16,4), kind='hist')
df_groupby_pagepath.plot( y='pageviews', bins=50, alpha=0.5, figsize=(16,4), kind='hist',ax=ax)
<matplotlib.axes._subplots.AxesSubplot at 0x112ca7048>

png

ほとんどのページが、15-20 PageView 以下 であることがわかります。
累積度数もプロットしたグラフを描いてみます。

import pandas as pd
df_pareto = pd.DataFrame(df_groupby_pagepath.groupby("pageviews").size())
df_pareto = df_pareto.sort_values(by="pageviews", ascending=True)
df_pareto.columns = ['count']
df_pareto["cumsum_pageview"] = np.cumsum(df_pareto["count"] * df_pareto.index)
df_pareto["cumsum_pageview_percent"] = df_pareto["cumsum_pageview"] / sum(df_pareto.index * df_pareto['count']) * 100
df_pareto["cumsum_count"] = np.cumsum(df_pareto["count"])
df_pareto["cumsum_count_percent"] = df_pareto["cumsum_count"] / sum(df_pareto['count']) * 100
df_pareto
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
count cumsum_pageview cumsum_pageview_percent cumsum_count cumsum_count_percent
pageviews
1 258 258 1.153691 258 27.771798
2 110 478 2.137459 368 39.612487
3 51 631 2.821625 419 45.102260
4 42 799 3.572866 461 49.623251
5 31 954 4.265975 492 52.960172
6 28 1122 5.017216 520 55.974166
7 31 1339 5.987569 551 59.311087
8 12 1435 6.416849 563 60.602799
9 22 1633 7.302240 585 62.970936
10 14 1773 7.928274 599 64.477933
11 20 1993 8.912042 619 66.630786
12 13 2149 9.609623 632 68.030140
13 11 2292 10.249072 643 69.214209
14 10 2432 10.875106 653 70.290635
15 14 2642 11.814157 667 71.797632
16 9 2786 12.458078 676 72.766416
17 12 2990 13.370299 688 74.058127
18 6 3098 13.853240 694 74.703983
19 10 3288 14.702857 704 75.780409
20 11 3508 15.686625 715 76.964478
21 5 3613 16.156151 720 77.502691
22 11 3855 17.238295 731 78.686760
23 3 3924 17.546841 734 79.009688
24 4 4020 17.976121 738 79.440258
25 6 4170 18.646872 744 80.086114
26 1 4196 18.763136 745 80.193757
27 3 4277 19.125341 748 80.516685
28 5 4417 19.751375 753 81.054898
29 4 4533 20.270089 757 81.485468
30 5 4683 20.940840 762 82.023681
... ... ... ... ... ...
139 2 13592 60.778965 899 96.770721
147 1 13739 61.436301 900 96.878364
150 2 14039 62.777803 902 97.093649
153 1 14192 63.461968 903 97.201292
154 1 14346 64.150606 904 97.308934
160 1 14506 64.866073 905 97.416577
164 1 14670 65.599428 906 97.524220
166 1 14836 66.341725 907 97.631862
169 1 15005 67.097438 908 97.739505
172 1 15177 67.866565 909 97.847147
175 1 15352 68.649108 910 97.954790
186 1 15538 69.480839 911 98.062433
189 1 15727 70.325985 912 98.170075
197 1 15924 71.206904 913 98.277718
199 1 16123 72.096767 914 98.385361
204 1 16327 73.008988 915 98.493003
208 1 16535 73.939096 916 98.600646
221 1 16756 74.927335 917 98.708288
258 1 17014 76.081027 918 98.815931
289 1 17303 77.373340 919 98.923574
328 1 17631 78.840048 920 99.031216
346 1 17977 80.387247 921 99.138859
374 1 18351 82.059652 922 99.246502
457 1 18808 84.103206 923 99.354144
491 1 19299 86.298797 924 99.461787
513 1 19812 88.592765 925 99.569429
533 1 20345 90.976166 926 99.677072
641 1 20986 93.842508 927 99.784715
670 1 21656 96.838528 928 99.892357
707 1 22363 100.000000 929 100.000000

126 rows × 5 columns

import matplotlib.pyplot as plt
fig, ax1 = plt.subplots(figsize=(15,8))
data_num = len(df_pareto)

ax1.bar(range(data_num), df_pareto["count"])
ax1.set_xticks(range(data_num))
ax1.set_xticklabels(df_pareto.index.tolist())
ax1.set_xlabel("label")
ax1.set_ylabel("counts")

ax2 = ax1.twinx()
ax2.plot(range(data_num), df_pareto["cumsum_count_percent"], c="k", marker="o")
ax2.set_ylim([0, 100])
ax2.grid(True, which='both', axis='y')
ax3 = ax1.twinx()
ax3.plot(range(data_num), df_pareto["cumsum_pageview_percent"], c="k", marker="x")
ax3.set_ylim([0, 100])
ax3.grid(True, which='both', axis='y')
ax1.set_title("Cumulativefrequency Graph")
plt.show()

png

全体の20%のページのPageViewが80% を占めていそうな雰囲気です。
PageView の閾値は80%点を指定します。


データ取得、加工までのスクリプトをまとめる

以下、データ取得、加工まで行うスクリプトをまとめます。

# ----------------
#  データ取得
# --------
from google2pandas import *
view_id = 'YOUR_VIEW_ID'
query = {
    'reportRequests': [{
        'viewId' : view_id,
        'dateRanges': [{
            'startDate' : '180daysAgo',
            'endDate'   : 'today'}],
        'dimensions' : [
            {'name' : 'ga:pagePath'}, 
            {'name' : 'ga:previousPagePath'},
        ],
        'metrics'   : [
            {'expression' : 'ga:pageviews'},
            {'expression' : 'ga:exits'},
        ],
    }]
}
conn = GoogleAnalyticsQueryV4(secrets='./ga_client.json')
df = conn.execute_query(query)

# ----------------
#  # 型変換
# --------
import numpy as np
df['exits'] = df['exits'].astype(np.int64)
df['pageviews'] = df['pageviews'].astype(np.int64)

# ----------------
#  データの加工
# --------

## データ抽出
# previousPagePath が `(entrance)` のデータを除外
df_excluded_entrance = df[df['previousPagePath'] != '(entrance)']
# previousPagePath ごとの合計を算出
df_groupby_pagepath = df_excluded_entrance.groupby('previousPagePath').sum()
# 上位20%のデータのみ抽出する
import pandas as pd
df_cutback = df_groupby_pagepath[df_groupby_pagepath['pageviews'] > df_groupby_pagepath.quantile(0.80)["pageviews"]]
df_edited = df_excluded_entrance[df_excluded_entrance['previousPagePath'].isin(df_cutback.index.tolist())]

## 元データに対して処理を行い、最終的なアウトプットへ加工する
page_grouped = df_edited.groupby(["previousPagePath","pagePath"]).sum()
del page_grouped["exits"]
page_grouped['pageview_percent'] = page_grouped.groupby(level=0).apply(lambda x: 100 * x / float(x.sum()))['pageviews']
page_grouped = page_grouped.reset_index()
page_grouped = page_grouped[(page_grouped['pageview_percent']  >= 10) & ~(page_grouped['previousPagePath'] == page_grouped['pagePath'])]

# pandas での編集結果を辞書にする    
record_dicts = page_grouped.to_dict(orient="records")
result_dict = {}
for record_dict in record_dicts:
    dict_list = result_dict.get(record_dict.get("previousPagePath"), [])
    dict_list.append(record_dict)
    result_dict.update({record_dict.get("previousPagePath") : dict_list})

result_dict
WARNING:googleapiclient.discovery_cache:file_cache is unavailable when using oauth2client >= 4.0.0
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/googleapiclient/discovery_cache/__init__.py", line 36, in autodetect
    from google.appengine.api import memcache
ModuleNotFoundError: No module named 'google.appengine'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/googleapiclient/discovery_cache/file_cache.py", line 33, in <module>
    from oauth2client.contrib.locked_file import LockedFile
ModuleNotFoundError: No module named 'oauth2client.contrib.locked_file'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/googleapiclient/discovery_cache/file_cache.py", line 37, in <module>
    from oauth2client.locked_file import LockedFile
ModuleNotFoundError: No module named 'oauth2client.locked_file'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/googleapiclient/discovery_cache/__init__.py", line 41, in autodetect
    from . import file_cache
  File "/usr/local/lib/python3.6/site-packages/googleapiclient/discovery_cache/file_cache.py", line 41, in <module>
    'file_cache is unavailable when using oauth2client >= 4.0.0')
ImportError: file_cache is unavailable when using oauth2client >= 4.0.0





{'/?page=2': [{'pagePath': '/',
   'pageview_percent': 11.320754716981131,
   'pageviews': 6,
   'previousPagePath': '/?page=2'},
  {'pagePath': '/?page=3',
   'pageview_percent': 43.39622641509434,
   'pageviews': 23,
   'previousPagePath': '/?page=2'}],
 '/about/': [{'pagePath': '/',
   'pageview_percent': 30.76923076923077,
   'pageviews': 28,
   'previousPagePath': '/about/'},
  {'pagePath': '/categories/',
   'pageview_percent': 19.78021978021978,
   'pageviews': 18,
   'previousPagePath': '/about/'},
  {'pagePath': '/statistics/',
   'pageview_percent': 10.989010989010989,
   'pageviews': 10,
   'previousPagePath': '/about/'}],
 '/amp/blog/google-analytics-のテータを-python-て-アソシエーション分析-する/': [{'pagePath': '/blog/mezzanine-の-blog-に-関連記事-のレコメンド表示を組み込んでみる/',
   'pageview_percent': 15.625,
   'pageviews': 5,
   'previousPagePath': '/amp/blog/google-analytics-のテータを-python-て-アソシエーション分析-する/'}],
 '/blog/Block-multiple-requests-of-Wicket-Ajax/': [{'pagePath': '/blog/Wicket-AjaxButton-Controls-behavior-when-an-error-occurs-onSubmit-method/',
   'pageview_percent': 10.0,
   'pageviews': 4,
   'previousPagePath': '/blog/Block-multiple-requests-of-Wicket-Ajax/'},
  {'pagePath': '/blog/search-resutls-wicket-forms/',
   'pageview_percent': 12.5,
   'pageviews': 5,
   'previousPagePath': '/blog/Block-multiple-requests-of-Wicket-Ajax/'},
  {'pagePath': '/blog/wicket-ajax処理-を並列に動作させる/',
   'pageview_percent': 12.5,
   'pageviews': 5,
   'previousPagePath': '/blog/Block-multiple-requests-of-Wicket-Ajax/'}],
 '/blog/Calculate-coefficient-of-variation-with-python-scipy-and-numpy/': [{'pagePath': '/',
   'pageview_percent': 14.705882352941176,
   'pageviews': 5,
   'previousPagePath': '/blog/Calculate-coefficient-of-variation-with-python-scipy-and-numpy/'}],
 '/blog/Calculate-the-probability-of-binomial-distribution-with-python/': [{'pagePath': '/blog/pythonでポアソン分布の計算をする/',
   'pageview_percent': 12.612612612612613,
   'pageviews': 14,
   'previousPagePath': '/blog/Calculate-the-probability-of-binomial-distribution-with-python/'}],
 '/blog/Continuing-technical-blogging-with-VPS-for-3-years-what-got-lost-what-is-going-on-now/': [{'pagePath': '/',
   'pageview_percent': 33.333333333333336,
   'pageviews': 18,
   'previousPagePath': '/blog/Continuing-technical-blogging-with-VPS-for-3-years-what-got-lost-what-is-going-on-now/'}],
 '/blog/Default-FindBugs-Rules-In-Github-Repositories/': [{'pagePath': '/blog/Default-PMD-Rules-In-Github-Repositories/',
   'pageview_percent': 21.311475409836067,
   'pageviews': 13,
   'previousPagePath': '/blog/Default-FindBugs-Rules-In-Github-Repositories/'}],
 '/blog/Default-PMD-Rules-In-Github-Repositories/': [{'pagePath': '/blog/pmd-rulesetの一覧java/',
   'pageview_percent': 49.6124031007752,
   'pageviews': 64,
   'previousPagePath': '/blog/Default-PMD-Rules-In-Github-Repositories/'}],
 '/blog/Draw-a-correlogram-with-statsmodels/': [{'pagePath': '/',
   'pageview_percent': 14.285714285714286,
   'pageviews': 4,
   'previousPagePath': '/blog/Draw-a-correlogram-with-statsmodels/'}],
 '/blog/Get-Google-trend-data-with-pytrends/': [{'pagePath': '/blog/Merge-Google-Trend-results-with-pytrends/',
   'pageview_percent': 18.83116883116883,
   'pageviews': 29,
   'previousPagePath': '/blog/Get-Google-trend-data-with-pytrends/'}],
 "/blog/Implement-Paging-with-Elasticsearch-Java-Client's-SearchTemplateRequestBuilder/": [{'pagePath': '/blog/macos-el-capitan-に-elasticsearch-を-インストールしてjava-クライアントから検索してみる/',
   'pageview_percent': 12.76595744680851,
   'pageviews': 6,
   'previousPagePath': "/blog/Implement-Paging-with-Elasticsearch-Java-Client's-SearchTemplateRequestBuilder/"}],
 '/blog/Python-implements-statistical-test-method-that-can-be-used-for-AB-test/': [{'pagePath': '/',
   'pageview_percent': 12.244897959183673,
   'pageviews': 6,
   'previousPagePath': '/blog/Python-implements-statistical-test-method-that-can-be-used-for-AB-test/'}],
 '/blog/TEMPLATE_DEBUG-on-Djnago1.8/': [{'pagePath': '/blog/django-18からsettingspyのtemplatesが非推奨になって警告が出力される/',
   'pageview_percent': 18.51851851851852,
   'pageviews': 5,
   'previousPagePath': '/blog/TEMPLATE_DEBUG-on-Djnago1.8/'},
  {'pagePath': '/blog/django-runserver-実行時にログを全部出しする/',
   'pageview_percent': 18.51851851851852,
   'pageviews': 5,
   'previousPagePath': '/blog/TEMPLATE_DEBUG-on-Djnago1.8/'}],
 '/blog/The-data-of-the-site-operated-for-18-years-has-disappeared/': [{'pagePath': '/',
   'pageview_percent': 36.111111111111114,
   'pageviews': 13,
   'previousPagePath': '/blog/The-data-of-the-site-operated-for-18-years-has-disappeared/'},
  {'pagePath': '/blog/category/雑記/',
   'pageview_percent': 11.11111111111111,
   'pageviews': 4,
   'previousPagePath': '/blog/The-data-of-the-site-operated-for-18-years-has-disappeared/'}],
 '/blog/Try-Japanese-translation-of-rule-of-SonarQube/': [{'pagePath': '/blog/install-SonarQube-on-El-Capitan/',
   'pageview_percent': 68.29268292682927,
   'pageviews': 112,
   'previousPagePath': '/blog/Try-Japanese-translation-of-rule-of-SonarQube/'}],
 '/blog/Try-static-analysis-of-Python-using-SonarPython/': [{'pagePath': '/blog/install-SonarQube-on-El-Capitan/',
   'pageview_percent': 15.909090909090908,
   'pageviews': 14,
   'previousPagePath': '/blog/Try-static-analysis-of-Python-using-SonarPython/'}],
 '/blog/Wicket-AjaxButton-Controls-behavior-when-an-error-occurs-onSubmit-method/': [{'pagePath': '/blog/Block-multiple-requests-of-Wicket-Ajax/',
   'pageview_percent': 15.151515151515152,
   'pageviews': 5,
   'previousPagePath': '/blog/Wicket-AjaxButton-Controls-behavior-when-an-error-occurs-onSubmit-method/'},
  {'pagePath': '/blog/search-resutls-wicket-forms/',
   'pageview_percent': 24.242424242424242,
   'pageviews': 8,
   'previousPagePath': '/blog/Wicket-AjaxButton-Controls-behavior-when-an-error-occurs-onSubmit-method/'}],
 '/blog/With-python-statsmodel-calculate-the-verification-power-and-the-Sample-Size/': [{'pagePath': '/blog/Perform-python-analysis-of-variance/',
   'pageview_percent': 10.344827586206897,
   'pageviews': 6,
   'previousPagePath': '/blog/With-python-statsmodel-calculate-the-verification-power-and-the-Sample-Size/'}],
 '/blog/apache-wicketでrestapiを使う/': [{'pagePath': '/blog/rest-api-on-wicket7.3.0/',
   'pageview_percent': 55.172413793103445,
   'pageviews': 16,
   'previousPagePath': '/blog/apache-wicketでrestapiを使う/'}],
 '/blog/args4j-で-enumoptionhandler-を使う/': [{'pagePath': '/blog/args4j-条件付きチェックを実装する/',
   'pageview_percent': 34.04255319148936,
   'pageviews': 16,
   'previousPagePath': '/blog/args4j-で-enumoptionhandler-を使う/'},
  {'pagePath': '/blog/spring-boot-での-サブコマンドsubcommandsの実装案/',
   'pageview_percent': 25.53191489361702,
   'pageviews': 12,
   'previousPagePath': '/blog/args4j-で-enumoptionhandler-を使う/'}],
 '/blog/args4j-条件付きチェックを実装する/': [{'pagePath': '/blog/args4j-で-enumoptionhandler-を使う/',
   'pageview_percent': 51.851851851851855,
   'pageviews': 14,
   'previousPagePath': '/blog/args4j-条件付きチェックを実装する/'},
  {'pagePath': '/blog/spring-boot-での-サブコマンドsubcommandsの実装案/',
   'pageview_percent': 14.814814814814815,
   'pageviews': 4,
   'previousPagePath': '/blog/args4j-条件付きチェックを実装する/'}],
 '/blog/beatifulsoup4-で余分なhtmlタグbodyタグを除去する/': [{'pagePath': '/blog/beautifulsoup-て-style-タクscript-タクstyle-属性を除去する/',
   'pageview_percent': 67.6056338028169,
   'pageviews': 48,
   'previousPagePath': '/blog/beatifulsoup4-で余分なhtmlタグbodyタグを除去する/'}],
 '/blog/beautifulsoup-て-style-タクscript-タクstyle-属性を除去する/': [{'pagePath': '/blog/beatifulsoup4-で余分なhtmlタグbodyタグを除去する/',
   'pageview_percent': 21.333333333333332,
   'pageviews': 32,
   'previousPagePath': '/blog/beautifulsoup-て-style-タクscript-タクstyle-属性を除去する/'}],
 '/blog/category/mezzanine/': [{'pagePath': '/blog/category/mezzanine/?page=2',
   'pageview_percent': 15.625,
   'pageviews': 5,
   'previousPagePath': '/blog/category/mezzanine/'},
  {'pagePath': '/blog/django-で-amp-ページ-と-通常ページを振り分ける/',
   'pageview_percent': 15.625,
   'pageviews': 5,
   'previousPagePath': '/blog/category/mezzanine/'},
  {'pagePath': '/blog/djangomezzanine-templateにcritical-css-組み込む思索と施作-1/',
   'pageview_percent': 12.5,
   'pageviews': 4,
   'previousPagePath': '/blog/category/mezzanine/'},
  {'pagePath': '/blog/updated-from-mezzanine-4.2.3-to-4.3.0/',
   'pageview_percent': 12.5,
   'pageviews': 4,
   'previousPagePath': '/blog/category/mezzanine/'}],
 '/blog/category/雑記/': [{'pagePath': '/',
   'pageview_percent': 36.0,
   'pageviews': 18,
   'previousPagePath': '/blog/category/雑記/'},
  {'pagePath': '/blog/Continuing-technical-blogging-with-VPS-for-3-years-what-got-lost-what-is-going-on-now/',
   'pageview_percent': 10.0,
   'pageviews': 5,
   'previousPagePath': '/blog/category/雑記/'}],
 '/blog/cent-os-69-に-memcached-をインストールログの設定まで実施する/': [{'pagePath': '/blog/cent-os-74-に-memcached-をインストールログの設定まで実施する/',
   'pageview_percent': 58.96551724137931,
   'pageviews': 171,
   'previousPagePath': '/blog/cent-os-69-に-memcached-をインストールログの設定まで実施する/'}],
 '/blog/cent-os-69-上で稼働する-django-に-memcached-の-cache-設定をしてみる/': [{'pagePath': '/blog/cent-os-69-に-memcached-をインストールログの設定まで実施する/',
   'pageview_percent': 21.428571428571427,
   'pageviews': 6,
   'previousPagePath': '/blog/cent-os-69-上で稼働する-django-に-memcached-の-cache-設定をしてみる/'},
  {'pagePath': '/blog/centos-69-で稼働しているdjango-で-pylibmc-を使おうとして結構大変だった話/',
   'pageview_percent': 17.857142857142858,
   'pageviews': 5,
   'previousPagePath': '/blog/cent-os-69-上で稼働する-django-に-memcached-の-cache-設定をしてみる/'}],
 '/blog/cent-os-74-に-memcached-をインストールログの設定まで実施する/': [{'pagePath': '/blog/cent-os-69-に-memcached-をインストールログの設定まで実施する/',
   'pageview_percent': 63.13131313131313,
   'pageviews': 125,
   'previousPagePath': '/blog/cent-os-74-に-memcached-をインストールログの設定まで実施する/'}],
 '/blog/content-security-policy-適用後の経過を観察する-2017年11月/': [{'pagePath': '/blog/content-security-policy-csp-の-report-を-10-日くらい集計してポリシーを見直すの途中/',
   'pageview_percent': 17.24137931034483,
   'pageviews': 5,
   'previousPagePath': '/blog/content-security-policy-適用後の経過を観察する-2017年11月/'},
  {'pagePath': '/blog/content-security-policy-適用後の経過を観察する-2018年04月/',
   'pageview_percent': 24.137931034482758,
   'pageviews': 7,
   'previousPagePath': '/blog/content-security-policy-適用後の経過を観察する-2017年11月/'}],
 '/blog/control-error-message-by-component-on-wicket/': [{'pagePath': '/blog/search-resutls-wicket-forms/',
   'pageview_percent': 48.888888888888886,
   'pageviews': 44,
   'previousPagePath': '/blog/control-error-message-by-component-on-wicket/'}],
 '/blog/django-18からsettingspyのtemplatesが非推奨になって警告が出力される/': [{'pagePath': '/blog/TEMPLATE_DEBUG-on-Djnago1.8/',
   'pageview_percent': 20.0,
   'pageviews': 6,
   'previousPagePath': '/blog/django-18からsettingspyのtemplatesが非推奨になって警告が出力される/'},
  {'pagePath': '/blog/django-djangotemplateloaderscachedloader-について/',
   'pageview_percent': 13.333333333333334,
   'pageviews': 4,
   'previousPagePath': '/blog/django-18からsettingspyのtemplatesが非推奨になって警告が出力される/'}],
 '/blog/django-request-on-mezzanine/': [{'pagePath': '/blog/django-runserver-実行時にログを全部出しする/',
   'pageview_percent': 28.26086956521739,
   'pageviews': 13,
   'previousPagePath': '/blog/django-request-on-mezzanine/'}],
 '/blog/django-runserver-実行時にログを全部出しする/': [{'pagePath': '/blog/djangoのsettingspy内でloghandler-streamhandlerのログ出力先を指定する/',
   'pageview_percent': 23.280423280423282,
   'pageviews': 44,
   'previousPagePath': '/blog/django-runserver-実行時にログを全部出しする/'}],
 '/blog/elasticsearch-の-kuromoji-plugin-が削除されてindexclosedexceptionが発生する/': [{'pagePath': '/blog/macos-el-capitan-に-elasticsearch-を-インストールしてjava-クライアントから検索してみる/',
   'pageview_percent': 10.526315789473685,
   'pageviews': 4,
   'previousPagePath': '/blog/elasticsearch-の-kuromoji-plugin-が削除されてindexclosedexceptionが発生する/'}],
 '/blog/error-handling-on-wicket/': [{'pagePath': '/blog/delete-version-number-from-url-on-wicket/',
   'pageview_percent': 14.285714285714286,
   'pageviews': 5,
   'previousPagePath': '/blog/error-handling-on-wicket/'}],
 '/blog/google-analytics-の-時系列テータを-bokeh-て可視化する/': [{'pagePath': '/blog/bokeh-と-plotlyでヒストグラム-を描く/',
   'pageview_percent': 15.789473684210526,
   'pageviews': 6,
   'previousPagePath': '/blog/google-analytics-の-時系列テータを-bokeh-て可視化する/'},
  {'pagePath': '/blog/google-analytics-のテータを-python-てコレスホンテンス分析する/',
   'pageview_percent': 10.526315789473685,
   'pageviews': 4,
   'previousPagePath': '/blog/google-analytics-の-時系列テータを-bokeh-て可視化する/'}],
 '/blog/google-analytics-アフィニティ-カテゴリの英語の対訳を-bing-translate-api-で作成する/': [{'pagePath': '/blog/google-analytics-アフィニティカテゴリの日本語翻訳を返すpython-ファンクションを作成する/',
   'pageview_percent': 22.580645161290324,
   'pageviews': 7,
   'previousPagePath': '/blog/google-analytics-アフィニティ-カテゴリの英語の対訳を-bing-translate-api-で作成する/'}],
 '/blog/google-analytics-アフィニティカテゴリの日本語翻訳を返すpython-ファンクションを作成する/': [{'pagePath': '/blog/google-analytics-アフィニティ-カテゴリの英語の対訳を-bing-translate-api-で作成する/',
   'pageview_percent': 30.76923076923077,
   'pageviews': 28,
   'previousPagePath': '/blog/google-analytics-アフィニティカテゴリの日本語翻訳を返すpython-ファンクションを作成する/'}],
 '/blog/google-app-script-の-urlfetchapp-の-例外ハンドリングについて/': [{'pagePath': '/blog/google-apps-script-urlfetchapp-で-http-header-を設定する/',
   'pageview_percent': 15.071283095723015,
   'pageviews': 74,
   'previousPagePath': '/blog/google-app-script-の-urlfetchapp-の-例外ハンドリングについて/'}],
 '/blog/google-apps-script-urlfetchapp-で-http-header-を設定する/': [{'pagePath': '/blog/google-app-script-の-urlfetchapp-の-例外ハンドリングについて/',
   'pageview_percent': 37.735849056603776,
   'pageviews': 60,
   'previousPagePath': '/blog/google-apps-script-urlfetchapp-で-http-header-を設定する/'}],
 '/blog/google-data-studio-でヒストグラムを描画する/': [{'pagePath': '/',
   'pageview_percent': 10.0,
   'pageviews': 4,
   'previousPagePath': '/blog/google-data-studio-でヒストグラムを描画する/'}],
 '/blog/google-search-console-の-キーワードの共起ネットワーク図を-python-で描画する/': [{'pagePath': '/blog/検索キーワードの共起ネットワーク図を-cytoscape-で描画する/',
   'pageview_percent': 27.766990291262136,
   'pageviews': 143,
   'previousPagePath': '/blog/google-search-console-の-キーワードの共起ネットワーク図を-python-で描画する/'}],
 '/blog/google-search-console-の-キーワードを-python-sklearn-linearsvc-でクラス分類してカテゴリ分けする/': [{'pagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-randomforestclassifier-でクラス分類してカテゴリ分けする/',
   'pageview_percent': 16.27906976744186,
   'pageviews': 7,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-linearsvc-でクラス分類してカテゴリ分けする/'},
  {'pagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-の-ナイーブベイズ分類-で-カテゴリ分けする/',
   'pageview_percent': 27.906976744186046,
   'pageviews': 12,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-linearsvc-でクラス分類してカテゴリ分けする/'}],
 '/blog/google-search-console-の-キーワードを-python-sklearn-randomforestclassifier-でクラス分類してカテゴリ分けする/': [{'pagePath': '/blog/google-search-console-の-キーワードの共起ネットワーク図を-python-で描画する/',
   'pageview_percent': 15.873015873015873,
   'pageviews': 10,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-randomforestclassifier-でクラス分類してカテゴリ分けする/'},
  {'pagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-linearsvc-でクラス分類してカテゴリ分けする/',
   'pageview_percent': 15.873015873015873,
   'pageviews': 10,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-randomforestclassifier-でクラス分類してカテゴリ分けする/'},
  {'pagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-の-ナイーブベイズ分類-で-カテゴリ分けする/',
   'pageview_percent': 22.22222222222222,
   'pageviews': 14,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-randomforestclassifier-でクラス分類してカテゴリ分けする/'}],
 '/blog/google-search-console-の-キーワードを-python-sklearn-の-ナイーブベイズ分類-で-カテゴリ分けする/': [{'pagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-linearsvc-でクラス分類してカテゴリ分けする/',
   'pageview_percent': 12.32876712328767,
   'pageviews': 18,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-の-ナイーブベイズ分類-で-カテゴリ分けする/'},
  {'pagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-randomforestclassifier-でクラス分類してカテゴリ分けする/',
   'pageview_percent': 13.013698630136986,
   'pageviews': 19,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-の-ナイーブベイズ分類-で-カテゴリ分けする/'},
  {'pagePath': '/blog/google-search-console-の-キーワードを-python-でクラスタリングする/',
   'pageview_percent': 11.643835616438356,
   'pageviews': 17,
   'previousPagePath': '/blog/google-search-console-の-キーワードを-python-sklearn-の-ナイーブベイズ分類-で-カテゴリ分けする/'}],
 '/blog/google-tag-manager-の-カスタムjavascript内-で-this-のようなものを使う/': [{'pagePath': '/blog/gtmgoogle-tag-manager-て-ユーサのカテコリことのハナー配信メッセーシ配信-を行う/',
   'pageview_percent': 12.5,
   'pageviews': 4,
   'previousPagePath': '/blog/google-tag-manager-の-カスタムjavascript内-で-this-のようなものを使う/'}],
 '/blog/google-モバイルサイト認定を取得してみました/': [{'pagePath': '/blog/mezzanine-amp-対応のテーマを作成してみました/',
   'pageview_percent': 19.444444444444443,
   'pageviews': 7,
   'previousPagePath': '/blog/google-モバイルサイト認定を取得してみました/'},
  {'pagePath': '/blog/usage-of-django-compress-on-mezzanine/',
   'pageview_percent': 13.88888888888889,
   'pageviews': 5,
   'previousPagePath': '/blog/google-モバイルサイト認定を取得してみました/'},
  {'pagePath': '/blog/プログラマがgaiq-を取得した話/',
   'pageview_percent': 13.88888888888889,
   'pageviews': 5,
   'previousPagePath': '/blog/google-モバイルサイト認定を取得してみました/'}],
 '/blog/google-モバイルフレンドリーテストで出力された警告に対処する/': [{'pagePath': '/blog/google-モバイルフレンドリーテスト-をpythonを使って実施して駄目な部分を対応する/',
   'pageview_percent': 12.5,
   'pageviews': 5,
   'previousPagePath': '/blog/google-モバイルフレンドリーテストで出力された警告に対処する/'}],
 '/blog/gtm-を使ってmixpanel-のタグを設定する/': [{'pagePath': '/blog/onesignal-google-analyticsmixpanel-に-event-を送付する/',
   'pageview_percent': 11.363636363636363,
   'pageviews': 5,
   'previousPagePath': '/blog/gtm-を使ってmixpanel-のタグを設定する/'}],
 '/blog/htmlcompressor-maven-plugin-を使ってhtml-を圧縮する/': [{'pagePath': '/blog/jar-ファイル作成時にminify-maven-plugin-を使ってcssjavascript-を圧縮結合する/',
   'pageview_percent': 47.36842105263158,
   'pageviews': 18,
   'previousPagePath': '/blog/htmlcompressor-maven-plugin-を使ってhtml-を圧縮する/'}],
 '/blog/install-SonarQube-on-El-Capitan/': [{'pagePath': '/blog/Try-Japanese-translation-of-rule-of-SonarQube/',
   'pageview_percent': 32.18390804597701,
   'pageviews': 56,
   'previousPagePath': '/blog/install-SonarQube-on-El-Capitan/'}],
 '/blog/invisible-markup-on-wicket/': [{'pagePath': '/blog/wicket-条件でhtml等のリソースファイルの切り替えをする/',
   'pageview_percent': 11.764705882352942,
   'pageviews': 6,
   'previousPagePath': '/blog/invisible-markup-on-wicket/'}],
 '/blog/jar-ファイル作成時にminify-maven-plugin-を使ってcssjavascript-を圧縮結合する/': [{'pagePath': '/blog/htmlcompressor-maven-plugin-を使ってhtml-を圧縮する/',
   'pageview_percent': 24.59016393442623,
   'pageviews': 30,
   'previousPagePath': '/blog/jar-ファイル作成時にminify-maven-plugin-を使ってcssjavascript-を圧縮結合する/'}],
 '/blog/java-easybatchを使ってみる1/': [{'pagePath': '/blog/java-easybatchを使ってみる2/',
   'pageview_percent': 61.1764705882353,
   'pageviews': 52,
   'previousPagePath': '/blog/java-easybatchを使ってみる1/'}],
 '/blog/jpa-query-selecting-only-specific-columns/': [{'pagePath': '/blog/Several-queries-implemented-with-QueryDsl/',
   'pageview_percent': 10.169491525423728,
   'pageviews': 6,
   'previousPagePath': '/blog/jpa-query-selecting-only-specific-columns/'}],
 '/blog/mezzanine-の-blog-に-関連記事-のレコメンド表示を組み込んでみる/': [{'pagePath': '/amp/blog/google-analytics-のテータを-python-て-アソシエーション分析-する/',
   'pageview_percent': 13.793103448275861,
   'pageviews': 4,
   'previousPagePath': '/blog/mezzanine-の-blog-に-関連記事-のレコメンド表示を組み込んでみる/'},
  {'pagePath': '/blog/mezzanine-の-blog-に-関連記事-のレコメンド表示をカスタマイズする/',
   'pageview_percent': 13.793103448275861,
   'pageviews': 4,
   'previousPagePath': '/blog/mezzanine-の-blog-に-関連記事-のレコメンド表示を組み込んでみる/'}],
 '/blog/mezzanine-フロクの記事公開日の日付フォーマットを変更する/': [{'pagePath': '/blog/ssl configuration-on-mezzanine/',
   'pageview_percent': 13.793103448275861,
   'pageviews': 4,
   'previousPagePath': '/blog/mezzanine-フロクの記事公開日の日付フォーマットを変更する/'}],
 '/blog/my-first-scaling/': [{'pagePath': '/blog/category/雑記/',
   'pageview_percent': 10.256410256410257,
   'pageviews': 4,
   'previousPagePath': '/blog/my-first-scaling/'}],
 '/blog/nonencoded-querystring-on-python-requests/': [{'pagePath': '/blog/python-requests-post-リクエスト送信時にheader-を設定する/',
   'pageview_percent': 20.72072072072072,
   'pageviews': 23,
   'previousPagePath': '/blog/nonencoded-querystring-on-python-requests/'}],
 '/blog/onesignal-の-serviceworker-と-既存の-serviceworker-と-共存させる/': [{'pagePath': '/blog/onesignal-を使った-webpush-通知の実装について/',
   'pageview_percent': 25.333333333333332,
   'pageviews': 19,
   'previousPagePath': '/blog/onesignal-の-serviceworker-と-既存の-serviceworker-と-共存させる/'},
  {'pagePath': '/blog/serviceworker-の-webpush-について/',
   'pageview_percent': 17.333333333333332,
   'pageviews': 13,
   'previousPagePath': '/blog/onesignal-の-serviceworker-と-既存の-serviceworker-と-共存させる/'}],
 '/blog/onesignal-を使った-webpush-通知の実装について/': [{'pagePath': '/blog/onesignal-の-serviceworker-と-既存の-serviceworker-と-共存させる/',
   'pageview_percent': 27.419354838709676,
   'pageviews': 17,
   'previousPagePath': '/blog/onesignal-を使った-webpush-通知の実装について/'},
  {'pagePath': '/blog/serviceworker-の-webpush-について/',
   'pageview_percent': 11.290322580645162,
   'pageviews': 7,
   'previousPagePath': '/blog/onesignal-を使った-webpush-通知の実装について/'}],
 '/blog/page-speed-insight-v4-api-で-ページ統計情報を取得する/': [{'pagePath': '/blog/page-speed-insights-の-score-を-定期的に計測してdatastudio-てクラフ化する/',
   'pageview_percent': 33.333333333333336,
   'pageviews': 17,
   'previousPagePath': '/blog/page-speed-insight-v4-api-で-ページ統計情報を取得する/'}],
 '/blog/page-speed-insights-の-score-を-定期的に計測してdatastudio-てクラフ化する/': [{'pagePath': '/blog/page-speed-insight-v4-api-で-ページ統計情報を取得する/',
   'pageview_percent': 37.5,
   'pageviews': 18,
   'previousPagePath': '/blog/page-speed-insights-の-score-を-定期的に計測してdatastudio-てクラフ化する/'}],
 '/blog/pmd-rulesetの一覧java/': [{'pagePath': '/blog/Default-PMD-Rules-In-Github-Repositories/',
   'pageview_percent': 52.76381909547739,
   'pageviews': 105,
   'previousPagePath': '/blog/pmd-rulesetの一覧java/'}],
 '/blog/postgres-sql-fatal-role-xxxxxx-is-not-permitted-to-log-in-が発生する/': [{'pagePath': '/blog/postgresql-connection-to-database-failed-fe_sendauth-no-password-supplied/',
   'pageview_percent': 12.195121951219512,
   'pageviews': 5,
   'previousPagePath': '/blog/postgres-sql-fatal-role-xxxxxx-is-not-permitted-to-log-in-が発生する/'}],
 '/blog/python-folinum-を使い都道府県の夫婦年齢差をプロットする/': [{'pagePath': '/blog/python-folium-で都内の公園にまつわる情報を地図上に描画する/',
   'pageview_percent': 28.514851485148515,
   'pageviews': 144,
   'previousPagePath': '/blog/python-folinum-を使い都道府県の夫婦年齢差をプロットする/'},
  {'pagePath': '/blog/python-folium-指定できる-地図の-タイル-について/',
   'pageview_percent': 19.00990099009901,
   'pageviews': 96,
   'previousPagePath': '/blog/python-folinum-を使い都道府県の夫婦年齢差をプロットする/'}],
 '/blog/python-folium-で都内の公園にまつわる情報を地図上に描画する/': [{'pagePath': '/blog/python-folinum-を使い都道府県の夫婦年齢差をプロットする/',
   'pageview_percent': 22.804054054054053,
   'pageviews': 135,
   'previousPagePath': '/blog/python-folium-で都内の公園にまつわる情報を地図上に描画する/'},
  {'pagePath': '/blog/python-folium-指定できる-地図の-タイル-について/',
   'pageview_percent': 19.425675675675677,
   'pageviews': 115,
   'previousPagePath': '/blog/python-folium-で都内の公園にまつわる情報を地図上に描画する/'}],
 '/blog/python-foliumのコロプレス図で選択可能なfill_color-について/': [{'pagePath': '/blog/python-folinum-を使い都道府県の夫婦年齢差をプロットする/',
   'pageview_percent': 28.985507246376812,
   'pageviews': 40,
   'previousPagePath': '/blog/python-foliumのコロプレス図で選択可能なfill_color-について/'},
  {'pagePath': '/blog/python-folium-で都内の公園にまつわる情報を地図上に描画する/',
   'pageview_percent': 17.391304347826086,
   'pageviews': 24,
   'previousPagePath': '/blog/python-foliumのコロプレス図で選択可能なfill_color-について/'},
  {'pagePath': '/blog/python-folium-指定できる-地図の-タイル-について/',
   'pageview_percent': 14.492753623188406,
   'pageviews': 20,
   'previousPagePath': '/blog/python-foliumのコロプレス図で選択可能なfill_color-について/'}],
 '/blog/python-て-ga-のテータをユーサーあたりのpageviewてセクメント分けする/': [{'pagePath': '/blog/google-analytics-のテータを-python-てコレスホンテンス分析する/',
   'pageview_percent': 14.285714285714286,
   'pageviews': 4,
   'previousPagePath': '/blog/python-て-ga-のテータをユーサーあたりのpageviewてセクメント分けする/'}],
 '/blog/python3-ではbeautifulsoup3-を-pip-install-できない/': [{'pagePath': '/blog/python-pip-install-でunicodedecodeerror-が発生/',
   'pageview_percent': 17.857142857142858,
   'pageviews': 5,
   'previousPagePath': '/blog/python3-ではbeautifulsoup3-を-pip-install-できない/'}],
 '/blog/pythonでポアソン分布の計算をする/': [{'pagePath': '/blog/Calculate-the-probability-of-binomial-distribution-with-python/',
   'pageview_percent': 10.526315789473685,
   'pageviews': 10,
   'previousPagePath': '/blog/pythonでポアソン分布の計算をする/'}],
 '/blog/search-resutls-wicket-forms/': [{'pagePath': '/blog/control-error-message-by-component-on-wicket/',
   'pageview_percent': 25.203252032520325,
   'pageviews': 31,
   'previousPagePath': '/blog/search-resutls-wicket-forms/'}],
 '/blog/serviceworker-を-ssr-中心の-blog-に組み込む際に調べたこと感想等/': [{'pagePath': '/blog/serviceworker-の-webpush-について/',
   'pageview_percent': 14.285714285714286,
   'pageviews': 5,
   'previousPagePath': '/blog/serviceworker-を-ssr-中心の-blog-に組み込む際に調べたこと感想等/'}],
 '/blog/sonarqube-java-client-介して-web-api-を-実行する/': [{'pagePath': '/blog/sonarqube-web-api-を-python-から実行する/',
   'pageview_percent': 26.19047619047619,
   'pageviews': 11,
   'previousPagePath': '/blog/sonarqube-java-client-介して-web-api-を-実行する/'}],
 '/blog/sonarqube-owasp-dependency-check-plugin-を-インストールして使ってみる/': [{'pagePath': '/blog/category/sonarqube/',
   'pageview_percent': 12.244897959183673,
   'pageviews': 6,
   'previousPagePath': '/blog/sonarqube-owasp-dependency-check-plugin-を-インストールして使ってみる/'}],
 '/blog/sonarqube-web-api-を-python-から実行する/': [{'pagePath': '/blog/Try-static-analysis-of-Python-using-SonarPython/',
   'pageview_percent': 24.65753424657534,
   'pageviews': 18,
   'previousPagePath': '/blog/sonarqube-web-api-を-python-から実行する/'},
  {'pagePath': '/blog/sonarqube-java-client-介して-web-api-を-実行する/',
   'pageview_percent': 31.506849315068493,
   'pageviews': 23,
   'previousPagePath': '/blog/sonarqube-web-api-を-python-から実行する/'}],
 '/blog/spring-boot-での-サブコマンドsubcommandsの実装案/': [{'pagePath': '/blog/args4j-で-enumoptionhandler-を使う/',
   'pageview_percent': 11.764705882352942,
   'pageviews': 6,
   'previousPagePath': '/blog/spring-boot-での-サブコマンドsubcommandsの実装案/'},
  {'pagePath': '/blog/args4j-条件付きチェックを実装する/',
   'pageview_percent': 15.686274509803921,
   'pageviews': 8,
   'previousPagePath': '/blog/spring-boot-での-サブコマンドsubcommandsの実装案/'}],
 '/blog/wicket-条件でhtml等のリソースファイルの切り替えをする/': [{'pagePath': '/blog/How-to-redirect-to-external-site-on-Wicket/',
   'pageview_percent': 11.11111111111111,
   'pageviews': 4,
   'previousPagePath': '/blog/wicket-条件でhtml等のリソースファイルの切り替えをする/'},
  {'pagePath': '/blog/create-stateless-page-on-wicket/',
   'pageview_percent': 11.11111111111111,
   'pageviews': 4,
   'previousPagePath': '/blog/wicket-条件でhtml等のリソースファイルの切り替えをする/'},
  {'pagePath': '/blog/wicketでページ内遷移を実装する/',
   'pageview_percent': 11.11111111111111,
   'pageviews': 4,
   'previousPagePath': '/blog/wicket-条件でhtml等のリソースファイルの切り替えをする/'}],
 '/blog/wicketでbodyタグのcssを切り替える/': [{'pagePath': '/blog/invisible-markup-on-wicket/',
   'pageview_percent': 18.6046511627907,
   'pageviews': 8,
   'previousPagePath': '/blog/wicketでbodyタグのcssを切り替える/'},
  {'pagePath': '/blog/wicket-152-でcss-javascript-の-reference-出力をコントロールする/',
   'pageview_percent': 23.25581395348837,
   'pageviews': 10,
   'previousPagePath': '/blog/wicketでbodyタグのcssを切り替える/'}],
 '/blog/データマイニングツール-orange-でgoogle-search-console-の-キーワードを-wordcloud-にする/': [{'pagePath': '/blog/google-analytics-のテータを-python-て-アソシエーション分析-する/',
   'pageview_percent': 11.11111111111111,
   'pageviews': 13,
   'previousPagePath': '/blog/データマイニングツール-orange-でgoogle-search-console-の-キーワードを-wordcloud-にする/'}],
 '/blog/検索キーワードの共起ネットワーク図を-cytoscape-で描画する/': [{'pagePath': '/blog/google-search-console-の-キーワードの共起ネットワーク図を-python-で描画する/',
   'pageview_percent': 53.50877192982456,
   'pageviews': 61,
   'previousPagePath': '/blog/検索キーワードの共起ネットワーク図を-cytoscape-で描画する/'}],
 '/categories/': [{'pagePath': '/about/',
   'pageview_percent': 12.658227848101266,
   'pageviews': 10,
   'previousPagePath': '/categories/'},
  {'pagePath': '/statistics/',
   'pageview_percent': 20.253164556962027,
   'pageviews': 16,
   'previousPagePath': '/categories/'}],
 '/statistics/': [{'pagePath': '/',
   'pageview_percent': 18.181818181818183,
   'pageviews': 12,
   'previousPagePath': '/statistics/'},
  {'pagePath': '/categories/',
   'pageview_percent': 16.666666666666668,
   'pageviews': 11,
   'previousPagePath': '/statistics/'}]}

参考

以下、参考にしました。

この記事で作成したデータは、AMP ページで先読み対象ページの判断するための入力として使おうかと考えております。
以上です。

コメント