24
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

データ分析で説明変数間の相関が高いときどうすればよいか(多重共線性対策)

Last updated at Posted at 2019-03-05

この記事について

 データ分析の特徴量(説明変数)設計においては以下の2点が重要である。

  • 各説明変数と目的変数が一定の相関を持つこと
  • 各説明変数間の相関が高い状態 (多重共線性) を避けること

 今回、実データにおいて多重共線性 (Multicollinearity , 通称マルチコ ) に出くわしたので、その対処法について実際のデータ分析の経過とともに述べたい。

 コードは以下に載せてあるので、参照してほしい。

   Git

結論

 結論からいうと、

「既存の変数を組み合わせて、新しい特徴量を設計すればよい」

 ということである。それでは実際の例を見ていただきたい。

実証

今回のデータ分析の目的

 県によって男女比が異なる。そこで各県の男女比を説明する特徴量をさがす。

 ちなみにこの図は、各都道府県の女性100人当たりの男性の数を段階別に色分けしたものであり、東北や九州では女性が多く、東京付近では男性が多い傾向にあることを示している。

スクリーンショット 2019-03-06 0.18.32.png

図の引用元:
総務省によるH27年日本の人工性比マップ

用いたデータ

総務省統計局H27年国勢調査データ

前処理後のデータ

スクリーンショット 2019-03-06 0.20.59.png

データ分析

目的変数「男女比」を設計

# 目的変数「男女比」をつくる
# 男女比 = 男性人口総数 / 女性人口総数 を100分率で表した。
df_JN['男女比'] = 100 * (df_JN['人口総数[男]'] / df_JN['人口総数[女]'] )

特徴量は以下の通り

# 列名を出力
df_JN.columns

スクリーンショット 2019-03-06 0.27.26.png

特徴量が多いのでデータフレームの一部をピックアップ

# 特徴量が多いのでdf_JNの一部をピックアップ
df_pickup = df_JN.loc[:, ['人口総数', '年少人口(15歳未満人口)',  '老年人口(65歳以上人口)', 
                      '外国人人口','出生数','死亡数',  '男女比']]

データフレームの変数の全ての組み合わせについて散布図を出力

import seaborn as sns 
plt.figure(figsize=(2, 2)) # プロットサイズを設定
sns.pairplot(np.log(df_pickup), size=2.0) # df_pickupの変数の全ての組み合わせについて散布図を出力

ダウンロード.png

データフレームの分散・共分散行列を出力

# df_pickupの分散・共分散行列を見やすいヒートマップ形式にて出力
sns.heatmap(df_pickup.corr(), annot=True, fmt='.2f')

ダウンロード (1).png

考察

 目的変数である「男女比」を除く、説明変数間の相関が非常に高い。

 こうした場合、特徴量が複数あっても、1つの特徴量の説明力と、全ての特徴量での説明力はほぼ等しくなる。実際に主成分分析をしてみると、図と、主成分分析の寄与率から、そのことがよくわかる。

  • 散布図を見るとほとんどが第1主成分上に乗っている。(スケールに注意してほしい)
  • 第1主成分寄与率が異常に高い

ダウンロード (2).png

主成分寄与率
第一主成分の寄与率 第二主成分の寄与率 ... =  [9.97255362e-01 2.65543899e-03 6.99232348e-05 1.08576403e-05]

累積寄与率 =  [0.99725536 0.9999108  0.99998072 0.99999158]

対処法

「既存の変数を組み合わせ、新しい変数を作れば良い」

とゆうことで、「外国人人口」と「人口総数」を組み合わせて、新しい変数 「外国人密度」を作った。
# 「外国人人口」 と 「人口総数」 を組み合わせて、新しい変数 「外国人密度」 を作った。
df_pickup['外国人密度'] = df_pickup['外国人人口'] / df_pickup['人口総数']
データフレームの分散・共分散行列を再度出力
# もう一度df_pickupの分散・共分散行列を出力
sns.heatmap(df_pickup.corr(), annot=True, fmt='.2f')

ダウンロード (2).png

散布図と主成分寄与率

ダウンロード (4).png

第一主成分の寄与率 第二主成分の寄与率 ... =  [8.61849821e-01 1.37040725e-01 1.03870481e-03 5.75002946e-05]

累積寄与率 =  [0.86184982 0.99889055 0.99992925 0.99998675]

まとめ

 いまだに第一主成分が幅を効かせ過ぎている感は否めないが、

  • 分散・共分散行列を見ると、「外国人密度」が

    • 他の説明変数と相関が低く、
    • かつ男女比との相関が0.68とそこそこ高いこと
  • 散布図を見ると、第2主成分の広がり(分散)が大きくなっていること

  • 第一主成分寄与率が0.997から0.862まで下がったこと

から、説明変数間の相関が高いときに、既存の説明変数を組み合わせて新しい説明変数を設計することが有効であることが実証できた。

余談

 余談であるが、既存の変数を組み合わせる時にアドホックに「外国人密度」という変数を設計したのではなかった。

 この男女比の課題はゼミの課題として半年前に取り組んだものであった。その際自分は、

説明変数間の相関が異常に高く、かつそれらと目的変数「男女比」との相関が異常に低い

という悲惨な状態を打開しようと、以下の仮説のもとに「外国人密度」を設計したところ上手くいったのであった。

外国人密度が高い -> 外国人労働者が多い -> 工業地帯 -> 男性が多い -> 男女比が高い

 半年ほど経った現在、多変量解析の実践(上) という本で統計の勉強をしていると、「説明変数間の相関が高いときに、既存の説明変数を組み合わせて新しい説明変数を設計することが有効である」 と書かれていたので、この男女比の例を思い出し、実際に主成分分析も行いながら、実証してみたのだった。それが今回の記事をかくきっかけとなった。最後に、この本と自分を引き合わせてくれた友人に感謝して締めくくりとしたいと思う。

 

24
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?