kaeken(嘉永島健司)のTech探究ブログ

主に情報科学/情報技術全般に関する知見をポストします。(最近は、特にData Science、機械学習、深層学習、統計学、Python、数学、ビッグデータ)

R言語でWebページの総合ランキングを作る方法

概要

Webページを評価する切り口は、さまざまな種類があります。

  • 表示回数
  • クリック数
  • 直帰率
  • 平均滞在時間
  • CV数
  • 各種ソーシャルいいね数
  • ...

もし各切り口の単位がバラバラで、ボリュームも異なり、優劣がつけられない場合、

総合的に判断することが難しくなります。

このような場合、

多数の考慮すべき情報を統合し優先順位をつけて総合ランキングを作るには、

以下の標準化を使うことで、総合的な評価指標の作成が可能になります。

標準化:単位が異なる複数の変数から総合指標を作成する方法

標準化については、以下の分かりやすい説明記事をご覧ください。

https://bellcurve.jp/statistics/course/7801.html

標準化することで、まったく異なる対象(数学と国語など)を統一的に評価できるようになります。

今回は、以下の具体的な6種類のデータを使って、Webページの総合ランキングを作成する方法をご紹介します。

実装

準備

まず、上記データのエクセルファイルを準備します。

R言語では、エクセルファイルやCSVなど、さまざまなファイルを読み書きすることが可能です。

# xls/xlsx形式を読み込むreadxlパッケージのインストール
install.packages("readxl", dependencies = TRUE)

# パッケージの利用準備
library(readxl)

# エクセルファイルの1シート目を読み込む
data = read_excel("~/Downloads/page_log.xlsx", 1)

つぎに、読み込んだデータの中身を確認します。

データの列名の意味は、以下の通りです。

  • No : データ行番号
  • TITLE : ページタイトル
  • PV : ページビュー
  • New : 新規流入
  • Average Time : 平均滞在時間
  • FB : Facebookいいね数
  • Pocket : Pocket保存数
  • Hatebu : はてブ登録数
# 読み込んだデータサンプリング
head(data)

# A tibble: 6 x 8
     No TITLE      PV    New `Average Time`    FB Pocket Hatebu
  <dbl> <chr>   <dbl>  <dbl>          <dbl> <dbl>  <dbl>  <dbl>
1     1 title1 154321  86341            184   264     60     21
2     2 title2 132840 103214            243   457     32     48
3     3 title3 186789 364212            160   190     52     26
4     4 title4  66455  30547            130   256    105     50
5     5 title5 506487 430687            311   830   1651   1198
6     6 title6 303546 153054            164    74    124     68

桁数がバラバラです。

以下、各データの統計量です。

# 要約統計量の表示
summary(data)
       No           TITLE                 PV              New        
 Min.   : 1.00   Length:12          Min.   : 43088   Min.   :  2064  
 1st Qu.: 3.75   Class :character   1st Qu.:116244   1st Qu.: 41438  
 Median : 6.50   Mode  :character   Median :174461   Median : 88342  
 Mean   : 6.50                      Mean   :192949   Mean   :122096  
 3rd Qu.: 9.25                      3rd Qu.:236802   3rd Qu.:115923  
 Max.   :12.00                      Max.   :506487   Max.   :430687  
  Average Time         FB             Pocket            Hatebu       
 Min.   : 58.0   Min.   : 15.00   Min.   :  25.00   Min.   :   4.00  
 1st Qu.:158.5   1st Qu.: 86.75   1st Qu.:  43.25   1st Qu.:   9.25  
 Median :198.0   Median :131.00   Median :  52.00   Median :  23.50  
 Mean   :206.6   Mean   :215.00   Mean   : 192.25   Mean   : 123.83  
 3rd Qu.:278.5   3rd Qu.:258.00   3rd Qu.:  84.00   3rd Qu.:  48.50  
 Max.   :311.0   Max.   :830.00   Max.   :1651.00   Max.   :1198.00


# 必要なカラムだけの要約統計量の表示
summary(data[,3:8])
       PV              New          Average Time         FB        
 Min.   : 43088   Min.   :  2064   Min.   : 58.0   Min.   : 15.00  
 1st Qu.:116244   1st Qu.: 41438   1st Qu.:158.5   1st Qu.: 86.75  
 Median :174461   Median : 88342   Median :198.0   Median :131.00  
 Mean   :192949   Mean   :122096   Mean   :206.6   Mean   :215.00  
 3rd Qu.:236802   3rd Qu.:115923   3rd Qu.:278.5   3rd Qu.:258.00  
 Max.   :506487   Max.   :430687   Max.   :311.0   Max.   :830.00  
     Pocket            Hatebu       
 Min.   :  25.00   Min.   :   4.00  
 1st Qu.:  43.25   1st Qu.:   9.25  
 Median :  52.00   Median :  23.50  
 Mean   : 192.25   Mean   : 123.83  
 3rd Qu.:  84.00   3rd Qu.:  48.50  
 Max.   :1651.00   Max.   :1198.00

Rでの行列指定方法は、以下のとおりです。

# cf. Rでの行列指定方法

# 一般形式
var[行指定, 列指定]

# 全行, 3-8列目だけ選択
var[, 3:8]

# 全行, 2列目だけ削除
var[, -2]

# 5行目, 1-2列目だけ選択
var[5, 1:2]

さらに、標準偏差など統計量を一括取得するパッケージを導入します。

# cf. psychパッケージdescribeコマンドで標準偏差など統計量を一括取得

install.packages("psych", dependencies = TRUE)
library(psych)
describe(data)

             vars  n      mean        sd   median  trimmed       mad   min
No              1 12      6.50      3.61      6.5      6.5      4.45     1
TITLE*          2 12       NaN        NA       NA      NaN        NA   Inf
PV              3 12 192949.17 130451.96 174461.0 176581.5 110918.50 43088
New             4 12 122096.00 136667.32  88341.5 103240.1  74921.71  2064
Average Time    5 12    206.58     78.37    198.0    211.0     83.77    58
FB              6 12    215.00    228.75    131.0    173.5    114.16    15
Pocket          7 12    192.25    460.32     52.0     63.1     22.98    25
Hatebu          8 12    123.83    338.92     23.5     28.4     26.69     4
                max  range  skew kurtosis       se
No               12     11  0.00    -1.50     1.04
TITLE*         -Inf   -Inf    NA       NA       NA
PV           506487 463399  0.95     0.20 37658.24
New          430687 428623  1.26     0.12 39452.46
Average Time    311    253 -0.21    -1.22    22.62
FB              830    815  1.57     1.57    66.03
Pocket         1651   1626  2.63     5.41   132.88
Hatebu         1198   1194  2.63     5.42    97.84

標準化

それでは、まず各データをscale()で標準化します。

# scaleコマンドを使う
data_st <- scale(data[,3:8])

# describe
library(psych)
head(data_st)

              PV        New Average Time         FB     Pocket     Hatebu
[1,] -0.29611028 -0.2616207   -0.2881790  0.2142092 -0.2873013 -0.3034187
[2,] -0.46077626 -0.1381603    0.4647019  1.0579310 -0.3481288 -0.2237529
[3,] -0.04722173  1.7715720   -0.5944357 -0.1092904 -0.3046806 -0.2886658
[4,] -0.96966090 -0.6698675   -0.9772565  0.1792362 -0.1895428 -0.2178517
[5,]  2.40347350  2.2579721    1.3324291  2.6885437  3.1690042  3.1694223
[6,]  0.84779740  0.2265209   -0.5433929 -0.6163978 -0.1482670 -0.1647411

describe(data_st)

             vars  n mean sd median trimmed  mad   min  max range  skew
PV              1 12    0  1  -0.14   -0.13 0.85 -1.15 2.40  3.55  0.95
New             2 12    0  1  -0.25   -0.14 0.55 -0.88 2.26  3.14  1.26
Average Time    3 12    0  1  -0.11    0.06 1.07 -1.90 1.33  3.23 -0.21
FB              4 12    0  1  -0.37   -0.18 0.50 -0.87 2.69  3.56  1.57
Pocket          5 12    0  1  -0.30   -0.28 0.05 -0.36 3.17  3.53  2.63
Hatebu          6 12    0  1  -0.30   -0.28 0.08 -0.35 3.17  3.52  2.63
             kurtosis   se
PV               0.20 0.29
New              0.12 0.29
Average Time    -1.22 0.29
FB               1.57 0.29
Pocket           5.41 0.29
Hatebu           5.42 0.29

上記を確認すると、きちんと 平均(mean):0 標準偏差(sd):1 に標準化されていることがわかります。

参考までに、行列情報の表示方法です。

# cf. 行列情報の表示

# 行列の行数だけ表示
> nrow(data_st)
[1] 12

# 行列の列数だけ表示
> ncol(data_st)
[1] 6

標準化による総合指標を作成

標準化された6つの指標を合成して総合指標にします。

まず、データフレームに変換します。

data_st_df <- data.frame(data_st)
describe(data_st_df)
             vars  n mean sd median trimmed  mad   min  max range  skew
PV              1 12    0  1  -0.14   -0.13 0.85 -1.15 2.40  3.55  0.95
New             2 12    0  1  -0.25   -0.14 0.55 -0.88 2.26  3.14  1.26
Average.Time    3 12    0  1  -0.11    0.06 1.07 -1.90 1.33  3.23 -0.21
FB              4 12    0  1  -0.37   -0.18 0.50 -0.87 2.69  3.56  1.57
Pocket          5 12    0  1  -0.30   -0.28 0.05 -0.36 3.17  3.53  2.63
Hatebu          6 12    0  1  -0.30   -0.28 0.08 -0.35 3.17  3.52  2.63
             kurtosis   se
PV               0.20 0.29
New              0.12 0.29
Average.Time    -1.22 0.29
FB               1.57 0.29
Pocket           5.41 0.29
Hatebu           5.42 0.29

そして、すべて同じ重み付けをする場合、項目の平均を掛け合わせて、scoreカラムに代入します。

data_st_df$score <- apply(data_st_df[,1:6], 1, mean)
describe(data_st_df)
             vars  n mean   sd median trimmed  mad   min  max range  skew
PV              1 12    0 1.00  -0.14   -0.13 0.85 -1.15 2.40  3.55  0.95
New             2 12    0 1.00  -0.25   -0.14 0.55 -0.88 2.26  3.14  1.26
Average.Time    3 12    0 1.00  -0.11    0.06 1.07 -1.90 1.33  3.23 -0.21
FB              4 12    0 1.00  -0.37   -0.18 0.50 -0.87 2.69  3.56  1.57
Pocket          5 12    0 1.00  -0.30   -0.28 0.05 -0.36 3.17  3.53  2.63
Hatebu          6 12    0 1.00  -0.30   -0.28 0.08 -0.35 3.17  3.52  2.63
score           7 12    0 0.84  -0.14   -0.17 0.25 -0.82 2.50  3.33  2.10
             kurtosis   se
PV               0.20 0.29
New              0.12 0.29
Average.Time    -1.22 0.29
FB               1.57 0.29
Pocket           5.41 0.29
Hatebu           5.42 0.29
score            3.78 0.24

cf. apply(x, y, z)の使い方です。

apply(x, y, z)引数
x: データセット名
y: 1 ... 列方向に各行を計算
y: 2 ... 行方向に各列を計算
z: mean平均 or sd標準偏差 or sum合計 or ...

cf. PVだけ重要視するなど、もしすべて同じ重み付けをせず、異なる重み付けをしたい場合は、各指標ごとに固定の値で割り算します。

総合指標を結合

実データと標準化したデータをcbind()で結合します。

data_score <- cbind(data, data_st_df)
str(data_score)

'data.frame':  12 obs. of  15 variables:
 $ No          : num  1 2 3 4 5 6 7 8 9 10 ...
 $ TITLE       : chr  "title1" "title2" "title3" "title4" ...
 $ PV          : num  154321 132840 186789 66455 506487 ...
 $ New         : num  86341 103214 364212 30547 430687 ...
 $ Average Time: num  184 243 160 130 311 164 277 212 303 283 ...
 $ FB          : num  264 457 190 256 830 74 114 91 15 36 ...
 $ Pocket      : num  60 32 52 105 1651 ...
 $ Hatebu      : num  21 48 26 50 1198 ...
 $ PV          : num  -0.2961 -0.4608 -0.0472 -0.9697 2.4035 ...
 $ New         : num  -0.262 -0.138 1.772 -0.67 2.258 ...
 $ Average.Time: num  -0.288 0.465 -0.594 -0.977 1.332 ...
 $ FB          : num  0.214 1.058 -0.109 0.179 2.689 ...
 $ Pocket      : num  -0.287 -0.348 -0.305 -0.19 3.169 ...
 $ Hatebu      : num  -0.303 -0.224 -0.289 -0.218 3.169 ...
 $ score       : num  -0.2037 0.0586 0.0712 -0.4742 2.5035 ...
 

head(data_score, 3)

  No  TITLE     PV    New Average Time  FB Pocket Hatebu          PV
1  1 title1 154321  86341          184 264     60     21 -0.29611028
2  2 title2 132840 103214          243 457     32     48 -0.46077626
3  3 title3 186789 364212          160 190     52     26 -0.04722173
         New Average.Time         FB     Pocket     Hatebu       score
1 -0.2616207   -0.2881790  0.2142092 -0.2873013 -0.3034187 -0.20373681
2 -0.1381603    0.4647019  1.0579310 -0.3481288 -0.2237529  0.05863578
3  1.7715720   -0.5944357 -0.1092904 -0.3046806 -0.2886658  0.07121298

少し整形して、見やすくします。

data_score <- cbind(data[,1:2], data_st_df$score)
colnames(data_score) <- c("No", "Title", "Score")
data_score

   No   Title        Score
1   1  title1 -0.203736806
2   2  title2  0.058635784
3   3  title3  0.071212976
4   4  title4 -0.474157196
5   5  title5  2.503474161
6   6  title6 -0.066413432
7   7  title7 -0.028503090
8   8  title8 -0.212493302
9   9  title9  0.009188198
10 10 title10 -0.207829963
11 11 title11 -0.627226978
12 12 title12 -0.822150352

cf. cbind() / rbind()

cbind() ... col bind 列方向のバインド
rbind() ... row bind 行方向のバインド

ランキングの作成

総合指標をランキング形式に変換します。

data_score$rank <- rank(data_score$Score)
data_score
   No   Title        Score rank
1   1  title1 -0.203736806    6
2   2  title2  0.058635784   10
3   3  title3  0.071212976   11
4   4  title4 -0.474157196    3
5   5  title5  2.503474161   12
6   6  title6 -0.066413432    7
7   7  title7 -0.028503090    8
8   8  title8 -0.212493302    4
9   9  title9  0.009188198    9
10 10 title10 -0.207829963    5
11 11 title11 -0.627226978    2
12 12 title12 -0.822150352    1


# ランクづけを大きいものほど小さくする降順に変更
data_score$rank <- rank(-data_score$Score)
data_score
   No   Title        Score rank
1   1  title1 -0.203736806    7
2   2  title2  0.058635784    3
3   3  title3  0.071212976    2
4   4  title4 -0.474157196   10
5   5  title5  2.503474161    1
6   6  title6 -0.066413432    6
7   7  title7 -0.028503090    5
8   8  title8 -0.212493302    9
9   9  title9  0.009188198    4
10 10 title10 -0.207829963    8
11 11 title11 -0.627226978   11
12 12 title12 -0.822150352   12

# ランクづけした後に、ランク昇順で表示
result <- data_score[order(data_score$rank), ]
result
   No   Title        Score rank
5   5  title5  2.503474161    1
3   3  title3  0.071212976    2
2   2  title2  0.058635784    3
9   9  title9  0.009188198    4
7   7  title7 -0.028503090    5
6   6  title6 -0.066413432    6
1   1  title1 -0.203736806    7
10 10 title10 -0.207829963    8
8   8  title8 -0.212493302    9
4   4  title4 -0.474157196   10
11 11 title11 -0.627226978   11
12 12 title12 -0.822150352   12

以上、

Web記事の総合ランキングを作る方法をご紹介しました。

発展

各項目ごとに重み付けする値を変更したり、

さまざまな項目の組み合わせで総合ランキングを作成したりできます。