この Blog はそれなりの更新頻度かと思います。
記事の品質問題は置いておき、だいたい 1 月あたり10 記事前後は作成していて、記事数に比例して PageView も増えていく傾向があります。
どの程度記事数と、PageView に相関関係があるのか気になりましたので、Python で計算してみました。
結果を記載します。


前提

相関関係の計算にあたり、前提となる情報を記載します。

この Blog について

2015 年に始めました。
月あたり 10 記事前後を 投稿しており、Web解析のため、Google Analytics、Google Search Console を使用しています。

必要なライブラリのインストール

!pip install --upgrade pip
!pip install pandas
!pip install google2pandas
!pip install oauth2client

Google2Pandas の使い方

Google Analytics のデータ取得には、google2pandasいうライブラリを使用しています。
使用する際は、Google Analytics サービスアカウントのキーの発行も必要になります。
以下の記事にまとめていますのでよろしければご確認ください。
Google2Pandas で、Google Analytics のデータを pandas Dataframe に変換する | Monotalk


Mezzanine の月次の記事数取得SQL

PostgresSQL 前提ですが、以下SQLを実行すると日次の記事数と累積記事数を取得できます。

  • Django から DB接続

    python3.6 manage.py dbshell     
    

  • SQL実行

    SELECT
        DATE_TRUNC('month', publish_date) as publish_month,
        COUNT(id) AS "Num of entry",
        SUM(COUNT(id)) OVER(ORDER BY DATE_TRUNC('month', publish_date) ASC) AS "Num of entries up to that month"
    FROM
        blog_blogpost AS blogpost
    GROUP BY publish_month    
    ORDER BY publish_month ASC;            
    

  • 出力結果

         publish_month      | Num of entry | Num of entries up to that month 
    ------------------------+--------------+---------------------------------
     2015-04-01 00:00:00+09 |            1 |                               1
     2015-05-01 00:00:00+09 |            1 |                               2
     2015-06-01 00:00:00+09 |            4 |                               6
     2015-09-01 00:00:00+09 |            1 |                               7
     2015-11-01 00:00:00+09 |            3 |                              10
     2015-12-01 00:00:00+09 |            9 |                              19
     2016-01-01 00:00:00+09 |            9 |                              28
     2016-03-01 00:00:00+09 |            3 |                              31
     2016-04-01 00:00:00+09 |            8 |                              39
     2016-05-01 00:00:00+09 |           19 |                              58
     2016-06-01 00:00:00+09 |           14 |                              72
     2016-07-01 00:00:00+09 |            9 |                              81
     2016-08-01 00:00:00+09 |           16 |                              97
     2016-09-01 00:00:00+09 |            6 |                             103
     2016-10-01 00:00:00+09 |           11 |                             114
     2016-11-01 00:00:00+09 |           13 |                             127
     2016-12-01 00:00:00+09 |            7 |                             134
     2017-01-01 00:00:00+09 |           24 |                             158
     2017-02-01 00:00:00+09 |           12 |                             170
     2017-03-01 00:00:00+09 |           11 |                             181
     2017-04-01 00:00:00+09 |           14 |                             195
     2017-05-01 00:00:00+09 |           13 |                             208
     2017-06-01 00:00:00+09 |           18 |                             226
     2017-07-01 00:00:00+09 |           25 |                             251
     2017-08-01 00:00:00+09 |           27 |                             278
     2017-09-01 00:00:00+09 |           18 |                             296
     2017-10-01 00:00:00+09 |           16 |                             312
     2017-11-01 00:00:00+09 |           19 |                             331
     2017-12-01 00:00:00+09 |           16 |                             347
     2018-01-01 00:00:00+09 |           23 |                             370
     2018-02-01 00:00:00+09 |           13 |                             383
     2018-03-01 00:00:00+09 |           12 |                             395
     2018-04-01 00:00:00+09 |           16 |                             411
     2018-05-01 00:00:00+09 |            8 |                             419
     2018-06-01 00:00:00+09 |           10 |                             429
     2018-07-01 00:00:00+09 |            9 |                             438
     2018-08-01 00:00:00+09 |           22 |                             460
     2018-09-01 00:00:00+09 |           12 |                             472
     2018-10-01 00:00:00+09 |            8 |                             480
     2018-11-01 00:00:00+09 |            5 |                             485
     2018-12-01 00:00:00+09 |            7 |                             492
     2019-01-01 00:00:00+09 |            9 |                             501
     2019-02-01 00:00:00+09 |            8 |                             509
     2019-03-01 00:00:00+09 |            2 |                             511
    (44 行)
    

合計 511 記事 結構書いたなと思います。

Google Analytics データの取得

google2pandas使います。
過去にgoogle2pandas使い方について、Google2Pandas で、Google Analytics のデータを pandas Dataframe に変換する | Monotalkまとめました。よろしければこちらもご確認ください。

from google2pandas import *
view_id = '103185238'
query = {
    'reportRequests': [{
        'viewId' : view_id,
        'dateRanges': [{
            'startDate' : '1825daysAgo',
            'endDate'   : 'today'}],
        'dimensions' : [
            {'name' : 'ga:yearMonth'}
        ],
        'metrics'   : [
            {'expression' : 'ga:pageViews'}
        ]
    }]
}
conn = GoogleAnalyticsQueryV4(secrets='./ga_client.json')
df = conn.execute_query(query)

# 出力
df['pageViews'] = df['pageViews'].astype(int)
ga_page_views = df.sort_values('yearMonth', ascending=True)
ga_page_views

yearMonthpageViews
0201506646
1201507920
2201508314
3201509163
4201510121
5201511970
6201512504
7201601642
8201602251
9201603385
10201604432
11201605664
12201606913
13201607946
142016081145
152016091267
162016101481
172016112847
182016123734
192017015911
2020170211972
212017032390
222017042405
232017053114
242017063955
252017074244
262017084448
272017095644
282017106985
292017118005
302017127844
312018018804
3220180210040
3320180312893
3420180413694
3520180516909
3620180618984
3720180718341
3820180819236
3920180919010
4020181020003
4120181120071
4220181224221
4320190124895
4420190224356
452019034878

相関関係を求める

月次の記事数の増加量と、Pageview の相関関係を求めます。

import pandas as pd   
# gist に up した Mezzanine の月次の投稿数を取得    
monthly_entries = pd.read_csv('https://gist.githubusercontent.com/kemsakurai/ef86122b072e509e3968d4e5cea3bd5f/raw/35fd7f8c5a16cd2fcf318a811c32a32ef42181b8/Number%2520of%2520blog%2520posts%2520per%2520month.tsv',sep='\t')
# YYYY-MM-DD を yearMonth の形式に変換する    
# - を除去
monthly_entries['yearMonth'] = monthly_entries['YYYY-MM-DD'].str.replace("-","").str[0:6]
# dataframe を inner join で結合    
merge_df = pd.merge(monthly_entries, ga_page_views, how='inner')
# Entry と、PageView の散布図を描画
merge_df.plot(kind='scatter', x='Num of entries up to that month', y='pageViews')

<matplotlib.axes._subplots.AxesSubplot at 0x119ee3c18>

20190309_output_7_1.png - Google ドライブ

合計記事数が増えれば、PageView が増えると言えそうです。
続いて時系列グラフを描きます。

merge_df.plot(x="yearMonth", subplots=True, sharex=True,figsize=(15, 10))

array([<matplotlib.axes._subplots.AxesSubplot object at 0x11aee16d8>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x11af0cbe0>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x11b125080>],
      dtype=object)

20190309_output_9_1.png - Google ドライブ

2017年にPageView が上がり、その後下がってるのは監視サービスを導入したためです。
監視ボットのアクセスがGoogle Analytics に記録されていたようです。
続いてdf.corr()相関係数を求めます。

del merge_df['Num of entry']
merge_df.corr()

Num of entries up to that monthpageViews
Num of entries up to that month1.0000000.876561
pageViews0.8765611.000000

0.876561正の相関があることがわかります。

デバイスごとの PageView との相関を計算する

PageView 全体での相関は計算しました。今度はデバイスごとでどのような相関を示すのか計算してみます。
デバイスごとのデータを取得するには、Google Analytics のデータ取得時にディメンションとしてga:deviceCategory追加します。

from google2pandas import *
view_id = '103185238'
query = {
    'reportRequests': [{
        'viewId' : view_id,
        'dateRanges': [{
            'startDate' : '1825daysAgo',
            'endDate'   : 'today'}],
        'dimensions' : [
            {'name' : 'ga:yearMonth'},
            {'name' : 'ga:deviceCategory'}
        ],
        'metrics'   : [
            {'expression' : 'ga:pageViews'}
        ]
    }]
}
conn = GoogleAnalyticsQueryV4(secrets='./ga_client.json')
df = conn.execute_query(query)

# 出力
df['pageViews'] = df['pageViews'].astype(int)
ga_page_views = df.sort_values('yearMonth', ascending=True)
ga_page_views

yearMonthdeviceCategorypageViews
0201506desktop624
1201506mobile22
2201507desktop915
3201507mobile5
4201508desktop309
5201508mobile5
6201509desktop160
7201509mobile2
8201509tablet1
9201510desktop117
10201510mobile4
11201511desktop942
12201511mobile28
14201512mobile44
15201512tablet4
13201512desktop456
16201601desktop536
17201601mobile100
18201601tablet6
19201602desktop232
20201602mobile18
21201602tablet1
22201603desktop359
23201603mobile26
24201604desktop389
25201604mobile40
26201604tablet3
29201605tablet6
27201605desktop547
28201605mobile111
............
102201806desktop17387
103201806mobile1359
104201806tablet238
105201807desktop16958
106201807mobile1179
107201807tablet204
108201808desktop17171
109201808mobile1880
110201808tablet185
113201809tablet187
111201809desktop16412
112201809mobile2411
114201810desktop18044
115201810mobile1734
116201810tablet225
117201811desktop18362
118201811mobile1313
119201811tablet396
120201812desktop21959
121201812mobile1776
122201812tablet486
124201901mobile1853
123201901desktop22544
125201901tablet498
127201902mobile1451
126201902desktop22401
128201902tablet504
130201903mobile444
129201903desktop6917
131201903tablet85

132 rows × 3 columns

deviceCategory が列に追加され、desktop、tablet、mobile が設定されています。

import pandas as pd   
# gist に up した Mezzanine の月次の投稿数を取得    
monthly_entries = pd.read_csv('https://gist.githubusercontent.com/kemsakurai/ef86122b072e509e3968d4e5cea3bd5f/raw/35fd7f8c5a16cd2fcf318a811c32a32ef42181b8/Number%2520of%2520blog%2520posts%2520per%2520month.tsv',sep='\t')
# YYYY-MM-DD を yearMonth の形式に変換する    
# - を除去
monthly_entries['yearMonth'] = monthly_entries['YYYY-MM-DD'].str.replace("-","").str[0:6]
# dataframe を inner join で結合    
merge_df = pd.merge(monthly_entries, ga_page_views, how='inner')

# Entry と、PageView の散布図を描画
# Deviceごとに色を変える
colors = {'desktop':'red', 'tablet':'blue', 'mobile':'green'}
merge_df.plot(kind='scatter', x='Num of entries up to that month', y='pageViews',c=merge_df['deviceCategory'].apply(lambda x: colors[x]))

<matplotlib.axes._subplots.AxesSubplot at 0x11b946f28>

20190309_output_16_1.png - Google ドライブ

# deviceCategory で Groupby して必要な項目を取得、結果の相関係数を出力    
merge_df.groupby('deviceCategory')[['YYYY-MM-DD','yearMonth','pageViews','Num of entries up to that month']].corr()

pageViewsNum of entries up to that month
deviceCategory
desktoppageViews1.0000000.889307
Num of entries up to that month0.8893071.000000
mobilepageViews1.0000000.718562
Num of entries up to that month0.7185621.000000
tabletpageViews1.0000000.775839
Num of entries up to that month0.7758391.000000

deviceCategory desktopが最も強い、正の相関を示していて、deviceCategory mobile の 正の相関が最も弱いです。

Desktop と Mobile で 相関が異なる理由

以下が理由かと思います。

  • そもそも Mobile から閲覧する絶対数が少ない。
    このサイトのアクセスの90%がDesktopからのアクセスになります。
    そもそも絶対数が少ないかなと思います。
    技術ブログを閲覧するのは業務中ということでしょうか。

  • Mobileから流入のある記事が限られていて、そのページの検索順位の変動に大きく左右される。
    一部の記事でやけに Mobile からのアクセス率の高い記事があります。
    そのような記事数は少なくてそのページの検索順位の変動があった場合、閲覧数が増減しているように思いました。


参考

以下、参考にしました。

以上です。

コメント