Google Analytics のデータをINPUT に python で、因子分析をしてみます。
試してみた結果を記載します。


前提

OS 、Python の version は以下の通りです。

  • OS

    % sw_vers
    ProductName:    Mac OS X
    ProductVersion: 10.13.2
    BuildVersion:   17C88
    

  • Python

    % python3 -V
    Python 3.6.2
    


参考


Python3 の因子分析のライブラリについて

検索した限り、以下2つ見つかりました。
2つを使用してみます。


入力データについて

以下項目を持つ、csvを Google Analytics から、エクスポートしてINPUTとしました。
実際に使用するデータは、ページデータソースページビュー数平均ページ滞在時間閲覧開始数直帰率しました。

  • ページ (ページのURL)
  • データソース (amp か、web か)
  • ページビュー数
  • ページ別訪問数
  • 平均ページ滞在時間
  • 閲覧開始数
  • 直帰率
  • 離脱率
  • ページの価値

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

pandasskeatlearnfactor_analyzerインストールします。

python3 -m pip install pandas
python3 -m pip install sklearn
python3 -m pip install factor_analyzer


入力データの読み込み、加工

入力データの読み込み、項目編集

csvファイルを読み込み、加工します。

# pandas import
import pandas as pd
# csv 読み込み
df = pd.read_csv("Analytics_20180128-20180203.csv")
# 項目削除
del df["ページ別訪問数"]
del df["離脱率"]
del df["ページの価値"]

# データソースのflgカラムの作成、データソースの項目削除
df["web"] = [ 1 if i == "web" else 0 for i in df["データソース"]]
df["amp"] = [ 1 if i == "amp" else 0 for i in df["データソース"]]
del df["データソース"]

# 直帰率を、小数点表記に変換する
df['直帰率'] = df['直帰率'].str.rstrip('%').astype('float') / 100.0

# 平均ページ滞在時間 の表記を変換する
df['平均ページ滞在時間'] = pd.to_timedelta(df['平均ページ滞在時間']).astype('timedelta64[s]').astype(int)

# ページURLをindexに設定し、カラムからは削除
df.index = df["ページ"]
del df["ページ"]
df.sort_values(by=["ページビュー数"] ,ascending=False)

ページページビュー数平均ページ滞在時間閲覧開始数直帰率webamp
/blog/java-url文字列からクエリストリングを取得/94528780.782110
/blog/python-requests-post-リクエスト送信時にheader-を設定する/56535520.865410
/blog/google-spread-sheet-の-複数のシートのデータをスクリプトで統合マージする/52145460.913010
/search?q=cache:Wt8QOKLDOBYJ:https://www.monotalk.xyz/blog/lombokのfindbugs警告を抑制する/+&cd=1&hl=ja&ct=clnk&gl=jp1011.000010

341 rows × 6 columns

データの標準化

作成したデータテーブルのカラム値を標準化します。
標準化には、sklearn の StandardScaler を使います。

from sklearn.preprocessing import StandardScaler
# 標準化
sc = StandardScaler()
values_std = sc.fit_transform(df.values)
values_std

array([[ 2.58467064,  5.94160084,  3.14574038,  0.45427759,  0.48067341,
        -0.46675169],
       [-0.43301625,  5.02330879, -0.49545945, -2.38644223,  0.48067341,
        -0.46675169],
       [-0.32895808,  4.96715424, -0.49545945,  0.65013694,  0.48067341,
        -0.46675169],
       ..., 
       [-0.53707442, -0.46992747, -0.49545945,  0.65013694,  0.48067341,
        -0.46675169],
       [-0.43301625, -0.46992747, -0.37408612,  0.65013694,  0.48067341,
        -0.46675169],
       [-0.53707442, -0.46992747, -0.49545945,  0.65013694,  0.48067341,
        -0.46675169]])

sklearn.decomposition.FactorAnalysis で因子分析する

from sklearn.decomposition import FactorAnalysis
index_values = df.index.values
values = values_std
# plot したいので、因子数は2にする、random_state はNone(デフォルト値)
factor = FactorAnalysis(n_components=2, random_state=None).fit(values)

# 因子分析の結果?を出力
factor.components_

array([[ 0.98725411,  0.4116763 ,  0.98578738,  0.04322812,  0.3206467 ,
        -0.31276261],
       [ 0.11817429, -0.0616083 ,  0.12648898,  0.04306155, -0.93194494,
         0.93431777]])

# 平均
factor.mean_

array([  2.08370304e-17,   8.33481215e-17,   4.16740607e-17,
        -4.16740607e-16,   1.35440697e-16,  -5.20925759e-17])

# 共分散行列を出力
factor.get_covariance()

array([[ 1.0000519 ,  0.3991486 ,  0.98817038,  0.04776591,  0.20642784,
        -0.19836383],
       [ 0.3991486 ,  1.00002621,  0.39803253,  0.01514305,  0.18941819,
        -0.18631868],
       [ 0.98817038,  0.39803253,  0.99997623,  0.04806055,  0.19820871,
        -0.19013654],
       [ 0.04776591,  0.01514305,  0.04806055,  0.99998756, -0.02627004,
         0.02671303],
       [ 0.20642784,  0.18941819,  0.19820871, -0.02627004,  1.00003545,
        -0.97101902],
       [-0.19836383, -0.18631868, -0.19013654,  0.02671303, -0.97101902,
         0.99999416]])

# 精度行列を出力
factor.get_precision()

array([[  4.27254016e+01,  -2.36557247e-01,  -4.20379018e+01,
         -2.86957419e-02,  -3.00475908e-01,   1.47157956e-01],
       [ -2.36557247e-01,   1.20803168e+00,  -2.20213189e-01,
         -7.41847202e-05,  -7.01286958e-02,   6.81899771e-02],
       [ -4.20379018e+01,  -2.20213189e-01,   4.25755929e+01,
         -2.72843105e-02,   7.41503962e-02,  -2.11924382e-01],
       [ -2.86957419e-02,  -7.41847202e-05,  -2.72843105e-02,
          1.00370920e+00,   1.92430710e-02,  -1.90205991e-02],
       [ -3.00475908e-01,  -7.01286958e-02,   7.41503962e-02,
          1.92430710e-02,   1.75627293e+01,   1.69947583e+01],
       [  1.47157956e-01,   6.81899771e-02,  -2.11924382e-01,
         -1.90205991e-02,   1.69947583e+01,   1.75044451e+01]])

# 対数尤度を計算
#[【統計学】尤度って何?をグラフィカルに説明してみる。 - Qiita](https://qiita.com/kenmatsu4/items/b28d1b3b3d291d0cc698) を見て理解した気になりました。 
factor.score_samples(values)

array([-26.88222376, -21.17887927, -18.64562927, -15.95512399,
       -11.09015412, -16.2018379 ,  -9.03469648,  -8.38053526,
        -7.5960467 ,  -6.98834868,  -9.12641478,  -5.75128567,
        -6.04428732, -13.76494109,  -5.1603273 ,  -4.8643237 ,
        -8.95151992,  -5.21628783,  -5.66274943,  -5.45219356,
        -6.19236802,  -4.74118053,  -8.02732884,  -3.74213434,
        -3.73061889,  -7.58573433,  -7.45257518,  -5.39083205,
        -6.13522878,  -5.13772173,  -7.52599653,  -3.08423632,
       -22.94402411, -48.66462817,  -2.98914181,  -2.94775235,
       -12.73806209,  -3.9274978 ,  -4.49272897,  -8.04074106,
        -3.27355439,  -2.88928812,  -2.9552131 , -12.21994932,
        -5.1309399 ,  -5.19823993,  -8.74220578,  -9.84644612,
        -9.43528641, -18.57918352,  -3.83164182,  -2.41720592,
        -3.48025055,  -3.35169751,  -2.38112138,  -2.71525327,
        -2.77548072,  -2.58890443,  -2.47453018,  -3.76612387,
       -11.55612693,  -4.45319771,  -4.67763028,  -8.83333124,
        -2.49977192,  -5.28042037,  -6.37894785,  -3.28087184,
       -12.15324351,  -2.44656305,  -5.06810639, -11.32097508,
        -2.69906406,  -8.08841751,  -2.32321471,  -4.52195549,
        -5.02963703,  -2.70801801,  -2.23905223,  -3.77118053,
        -3.18384417,  -2.647561  ,  -6.16621286,  -7.6228201 ,
       -17.08287778,  -2.2414416 ,  -6.83780151,  -2.76768739,
        -2.64758064,  -3.92816078,  -2.80958223,  -3.20695896,
        -2.4588131 ,  -2.48254864,  -2.69777797,  -5.30077629,
        -3.62355096,  -2.35138092,  -2.98566481,  -4.31472279,
        -3.88684676,  -9.81443294,  -4.86163244,  -2.71380218,
        -2.70771654,  -6.08206004,  -4.90693932,  -5.84550425,
        -2.44325268,  -5.22006632,  -2.70880726,  -2.41818702,
        -2.73611274,  -5.32246521,  -2.47357184,  -5.22898078,
        -5.23092185,  -5.86799266,  -7.57528591,  -5.87101505,
        -8.23142046,  -3.69853499,  -7.57456095,  -2.75650964,
        -4.90436892,  -5.24108914,  -2.3901433 ,  -3.19472757,
        -2.39422975,  -6.65129952,  -2.74911553,  -5.34346357,
        -5.34561904,  -5.15909496,  -5.34895111,  -2.36317992,
        -7.57269797,  -7.38537204,  -7.38537204,  -4.90842926,
        -5.09564576,  -2.75738557,  -2.76077   ,  -2.75738557,
        -2.75738557,  -2.75738557,  -7.57275946,  -4.58243964,
        -2.75738557,  -3.65363545,  -4.58243964,  -2.9756133 ,
        -2.74509334, -58.6150682 ,  -2.74509334,  -5.35718726,
        -2.75569051,  -4.58243964,  -2.75738557,  -2.75738557,
        -2.75738557,  -2.75738557,  -2.75738557,  -2.74509334,
        -5.35718726,  -2.75738557,  -4.58243964,  -2.75738557,
        -2.75738557,  -4.58243964,  -4.58243964,  -2.74509334,
        -2.80441555,  -4.58243964,  -2.75569051,  -4.58243964,
        -2.76077   ,  -2.76077   ,  -2.74509334,  -2.76077   ,
        -2.74509334,  -7.57275946,  -2.80441555,  -2.76077   ,
        -3.10316551,  -2.75738557,  -5.89549343,  -2.80441555,
        -2.75738557,  -3.44217658,  -4.58243964,  -2.87602998,
        -2.75738557,  -5.26037821,  -2.57948141,  -2.74509334,
        -5.35718726,  -4.60001609,  -4.58243964,  -2.75738557,
        -2.75738557, -58.6150682 ,  -2.74509334,  -2.6324238 ,
        -4.71907566,  -2.76077   , -58.6150682 ,  -4.60001609,
        -4.58243964,  -2.76077   ,  -2.76077   ,  -4.58243964,
        -5.26037821,  -2.76077   ,  -2.65152588,  -4.64556143,
        -4.60001609,  -2.75738557,  -4.71907566,  -2.74509334,
        -2.75738557,  -2.74509334,  -4.16045985,  -4.95001077,
        -4.58243964,  -3.10316551,  -2.75738557,  -6.35218634,
        -4.58243964,  -2.75738557,  -4.58243964,  -2.76077   ,
        -4.58243964,  -2.75738557,  -4.58243964,  -2.74509334,
        -4.58243964,  -4.58243964,  -2.76077   ,  -4.71907566,
        -2.75738557,  -3.65363545,  -2.74509334,  -2.75738557,
        -4.60001609,  -2.76077   ,  -2.75738557,  -2.74509334,
        -3.44217658,  -2.75738557,  -2.74509334,  -4.58243964,
        -2.75738557,  -4.58243964,  -2.80441555,  -2.74509334,
        -2.74509334,  -2.75738557,  -4.58243964,  -2.80441555,
        -2.75738557,  -2.75738557,  -2.75738557,  -2.75738557,
        -2.75738557,  -4.58243964,  -2.57948141,  -2.75738557,
        -2.57684846,  -2.76077   ,  -2.76077   ,  -4.58243964,
        -2.75738557,  -2.75738557,  -3.10316551,  -4.60001609,
        -4.58243964,  -2.57948141,  -3.44217658,  -2.75738557,
        -2.74509334,  -2.75738557,  -2.76077   ,  -3.2586866 ,
        -4.60001609,  -2.75738557,  -3.2586866 ,  -2.9756133 ,
        -2.74509334,  -5.26037821,  -4.60001609,  -2.75738557,
        -2.75738557,  -4.60001609,  -2.75738557,  -4.60001609,
        -2.89409042,  -2.76077   ,  -2.75738557,  -2.74509334,
        -2.75738557,  -2.75738557,  -2.76077   ,  -2.76077   ,
        -3.89306321,  -4.58243964,  -3.63454366,  -2.76077   ,
        -2.75738557,  -2.60113937,  -4.58243964,  -2.76077   ,
        -2.74509334,  -2.76077   ,  -2.80441555,  -2.75738557,
        -2.87602998,  -5.35718726,  -2.75738557,  -2.75738557,
        -2.74509334,  -2.57948141,  -2.75738557,  -2.76077   ,
        -2.75738557,  -2.75738557,  -2.76077   ,  -2.75738557,
        -2.6750994 ,  -2.9756133 ,  -2.74509334,  -2.74509334,
        -3.75556402,  -2.9756133 ,  -2.75738557,  -4.58243964,
        -4.58243964,  -2.75738557,  -2.75738557,  -2.74509334,  -2.75738557])

# 平均対数尤度を計算する
factor.score(values)

-5.087489145362464

X_transformed = factor.fit_transform(values)
print("* 推定ノイズ分散")
print(factor.noise_variance_)
print("* 固有ベクトル")
print(factor.components_)
print("* 反復時の対数尤度")
print(factor.loglike_)
print("* 反復回数")
print(factor.n_iter_)

* 推定ノイズ分散
[ 0.01141607  0.82675325  0.01220002  0.99626459  0.02869978  0.02922401]
* 固有ベクトル
[[ 0.98725411  0.4116763   0.98578738  0.04322812  0.3206467  -0.31276261]
 [ 0.11817429 -0.0616083   0.12648898  0.04306155 -0.93194494  0.93431777]]
* 反復時の対数尤度
[-2769.6111439014703, -2532.8459135320918, -2322.1060227954972, -2132.7023670986919, -1976.0755036105688, -1861.9624988585206, -1791.7650498542228, -1756.3966117270038, -1741.8858151772272, -1736.9090900302376, -1735.4112214477689, -1734.9945834483028, -1734.8820469443217, -1734.8503220338521, -1734.8394217395453, -1734.8337985576372]
* 反復回数
16

グラフに描画する

%matplotlib inline
#プロット用のライブラリを利用
import matplotlib.pyplot as plt 
import matplotlib
font = {'family': 'IPAexGothic'}
matplotlib.rc('font', **font)
plt.figure(figsize=(16,14))
plt.scatter(X_transformed[::2,0],X_transformed[::2,1])
plt.xlabel('X')
plt.ylabel('Y')
count = 0
for xy in zip(X_transformed[::2,0], X_transformed[::2,1]):
    plt.annotate(index_values[count], xy=xy, textcoords='data')
    count = 1+ count

"因子分析グラフ"

出力された図から、因子を特定してみようかと思いましたが、何がなんだかよくわからず..断念します。

factor_analyzer を使って、因子分析する

続いて、factor_analyzer使います。
R の factanal 関数を使用した際に得られる戻り値を取得することができます。
個人的にはfactanal出力がわかりやすく思えたので、factor_analyzerわかりやすいです。

from factor_analyzer import FactorAnalyzer 
# 標準化したデータをコピーして新たにdataframeを作成する
df_std = pd.DataFrame(values_std)
df_std.index = df.index
df_std.columns = df.columns

# 因子数は2 を設定する
fa = FactorAnalyzer()
fa.analyze(df_std, 2, rotation=None)

# 因子負荷量を出力
fa.loadings

Factor1Factor2
ページビュー数0.8281000.561866
平均ページ滞在時間0.3955040.128913
閲覧開始数0.8106860.559416
直帰率-0.0156340.040196
web0.718495-0.690493
amp-0.6990670.676665

#  独自性を出力
fa.get_uniqueness()

Uniqueness
ページビュー数-0.001444
平均ページ滞在時間0.826958
閲覧開始数0.029841
直帰率0.998140
web0.006985
amp0.053429

平均ページ滞在時間と、直帰率 は独自性が強い(2因子の影響を受けていない)ということになるのかと思います。

#  寄与度、寄与率、累積寄与率の出力
fa.get_factor_variance()

Factor1Factor2
SS Loadings2.5045601.581530
Proportion Var0.4174270.263588
Cumulative Var0.4174270.681015

#  固有値を出力
fa.get_eigenvalues()

(   Original_Eigenvalues
 0              2.506915
 1              1.583361
 2              0.227129
 3             -0.001580
 4             -0.007516
 5             -0.222220,    Common_Factor_Eigenvalues
 0                   2.506915
 1                   1.583361
 2                   0.227129
 3                  -0.001580
 4                  -0.007516
 5                  -0.222220)

ドキュメントを読む限り、factor_analyzer は、因子分析の結果?の2次元配列は取得できなさそうです。
因子負荷量や、独自性の出力が行えるので、ざっくりデータを見る際は、factor_analyzer使い、その後、グラフにプロットする場合は、FactorAnalysis 、という使い分けをしようかと思います。 以上です。

コメント