3
2

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 3 years have passed since last update.

総合実験(3日目)Jupyter Notebookを使った多変量解析

Last updated at Posted at 2018-06-19

2016年に作った資料を公開します。もう既にいろいろ古くなってる可能性が高いです。

Jupyter Notebook (IPython Notebook) とは

  • Python という名のプログラミング言語が使えるプログラミング環境。計算コードと計算結果を同じ場所に時系列で保存できるので、実験系における実験ノートのように、いつどんな処理を行って何を得たのか記録して再現するのに便利。

  • 本実習では多変量解析のうち主成分分析(PCA; Principal Component Analysis)を行ないます。

  • 各自の画面中の IPython Notebook のセルに順次入力して(コピペ可)、「Shift + Enter」してください。

  • 最後に、課題を解いてもらいます。課題の結果を、指定する方法で指定するメールアドレスまで送信してください。

まずは基本統計量を計算する関数の作成から

# 平均値を求める関数
def average(data):
    sum = 0.0
    n = 0.0
    for x in data:
        sum += x
        n += 1.0
    return sum / n
# 分散を求める関数
def variance(data):
    ave = average(data)
    accum = 0.0
    n = 0.0
    for x in data:
        accum += (x - ave) ** 2.0
        n += 1.0
    return accum / n
# 標準偏差を求める関数
import math
standard_deviation = lambda data: math.sqrt(variance(data))
# リストの正規化をする(Z値に変換する)関数
def normalize(data):
    ave = average(data)
    std = standard_deviation(data)
    list = []
    for x in data:
        list.append((x - ave) / (std / float(len(data))))
    return list
# リストのリストの正規化をする(Z値に変換する)関数
def normalize2(data):
    list = []
    for x in data:
        list.append(normalize(x))
    return list

計算に必要ないろんなライブラリのインポート

# 図やグラフを図示するためのライブラリをインポートする。
import matplotlib.pyplot as plt
%matplotlib inline
import pandas as pd # データフレームワーク処理のライブラリをインポート
from pandas.tools import plotting # 高度なプロットを行うツールのインポート
import sklearn #機械学習のライブラリ
from sklearn.decomposition import PCA #主成分分析器
import numpy as np #数値計算用ライブラリ
# URL によるリソースへのアクセスを提供するライブラリをインポートする。
import urllib

実データ解析開始

  • データをダウンロードし、まずはデータの全体像を把握します。
# ウェブ上のリソースを指定する
url = 'https://raw.githubusercontent.com/maskot1977/ipython_notebook/master/toydata/sake_dataJ.txt'
# 指定したURLからリソースをダウンロードし、名前をつける。
urllib.urlretrieve(url, 'sake_dataJ.txt')
('sake_dataJ.txt', <httplib.HTTPMessage instance at 0x1164e9ab8>)
df = pd.read_csv('sake_dataJ.txt', sep='\t', na_values=".") # データの読み込み
pd.DataFrame(df).head() # 先頭N行を表示する。カラムのタイトルも確認する。
Pref Sake Shochu Bear Wine Whisky
0 Hokkaido 46476000 50642000 315300000 10488000 9749000
1 Aomori 17273000 11503000 83164000 1774000 3122000
2 Iwate 17120000 10220000 67803000 1458000 1870000
3 Miyagi 27859000 11768000 109850000 2824000 5049000
4 Akita 24153000 6240000 67894000 1242000 2099000
# 下記の関数にカラム名を入力すれば、Scatter Matrix が表示されます。
#plotting.scatter_matrix(df[['Sake', 'Shochu', 'Bear', 'Wine', 'Whisky']], figsize=(10, 10)) 
plotting.scatter_matrix(df[['Sake', 'Shochu', 'Bear', 'Wine', 'Whisky']], figsize=(10, 10), diagonal='kde') 
plt.show()

output_20_0.png

上図を「図1」と呼ぶことにします。課題1と4で、似たような図を作成してもらいます。

主成分分析

行をエントリとし、列を説明変数とする場合。

# 表形式のデータを、PCAにかけられる形に整形する。
# 行をエントリとし、列を説明変数とする場合。
x_labels = []
y_labels = []
data1 = []
for i, line in enumerate(open('sake_dataJ.txt')):
    if i == 0:
        a = line.strip().split("\t")
        x_labels = []
        for j, val in enumerate(a):
            if j == 0:
                continue
            else:
                x_labels.append(val)
    else:
        a = line.strip().split("\t")
        b = []
        for j, val in enumerate(a):
            if j == 0:
                y_labels.append(val)
            else:
                b.append(float(val))
        data1.append(b)
data1 = normalize2(data1)
#主成分分析の実行
pca = PCA()
pca.fit(data1)
PCA(copy=True, n_components=None, whiten=False)
# 因子負荷量の確認。左から順に第一変数、第二変数、、、
# 上から順に因子1、因子2、、、
pd.DataFrame(list(pca.components_), columns=x_labels)
Sake Shochu Bear Wine Whisky
0 0.665066 -0.745030 0.020380 0.015191 0.044392
1 0.595199 0.492514 -0.291951 -0.423517 -0.372246
2 -0.033083 -0.000164 -0.030030 -0.674053 0.737331
3 0.048279 0.048577 -0.844658 0.407499 0.340303
4 0.447214 0.447214 0.447214 0.447214 0.447214
# それぞれの因子にどの説明変数がどの程度用いられているか図示する
plt.figure(figsize=(5, 5))
for x, y, name in zip(pca.components_[0], pca.components_[1], x_labels):
    plt.text(x, y, name, alpha=0.8, size=15)
plt.scatter(pca.components_[0], pca.components_[1])
plt.title("Factor loadings")
plt.xlabel("Factor 1")
plt.ylabel("Factor 2")
plt.show()

output_26_0.png

# 主成分に対する因子の寄与率を確認。左から順に第一主成分、第二主成分、、、
list(pca.explained_variance_ratio_)
[0.84883499643508986,
 0.13109085939363213,
 0.013441153902092553,
 0.006632990269185365,
 1.097158765092042e-31]
# 累積寄与率を図示する
import matplotlib.ticker as ticker
plt.gca().get_xaxis().set_major_locator(ticker.MaxNLocator(integer=True))
plt.plot([0] + list( np.cumsum(pca.explained_variance_ratio_)), "-o")
plt.xlabel("Number of principal components")
plt.ylabel("Cumulative contribution ratio")
plt.show()

output_28_0.png

# データを主成分空間に写像 = 次元圧縮
feature = pca.transform(data1)
# 次元圧縮後のデータ。左から順に第一主成分、第二主成分、、、
pd.DataFrame(feature, index=y_labels)
0 1 2 3 4
Hokkaido -1.110409 -0.360847 -0.005956 -0.081387 -1.848328e-16
Aomori -0.333849 0.009345 0.142182 -0.121610 -3.301751e-16
Iwate -0.056292 0.503782 0.018778 -0.158425 -6.492096e-16
Miyagi 0.408308 0.103275 0.165782 -0.058181 -6.292635e-16
Akita 1.443781 0.962598 0.042480 0.048677 -3.417578e-16
Yamagata 1.231049 0.744283 0.052815 0.017058 -1.316482e-16
Fukushima 0.860825 0.674256 0.124998 -0.052539 -2.086859e-16
Ibaraki 0.068851 0.176213 0.015612 -0.105348 -4.502962e-16
Tochigi -0.042050 0.188377 0.022389 -0.118697 -4.399736e-17
Gunma -0.635379 0.424675 -0.061466 -0.186559 -5.561106e-16
Saitama -0.701716 -0.169577 -0.010401 -0.107353 -1.087064e-16
Chiba -0.615565 -0.209105 -0.018429 -0.096634 -7.202464e-16
Tokyo -0.487767 -0.841145 -0.121137 0.043356 -7.148378e-16
Kanagawa -0.645375 -0.484661 0.043345 -0.049275 -8.301455e-16
Niigata 2.266970 1.107016 -0.038925 0.271340 -7.217689e-16
Toyama 1.449565 0.205898 0.014282 0.128808 -2.186333e-17
Ishikawa 1.233966 -0.036312 0.013812 0.115745 -4.581391e-16
Fukui 0.949785 -0.276469 0.053900 0.097084 -4.603907e-16
Yamanashi -0.498276 -0.141691 -0.971316 -0.018632 -5.392369e-16
Nagano 0.663382 0.499552 -0.184689 -0.054813 -4.997498e-16
Gifu 0.831055 -0.194526 0.005190 0.062385 -4.194302e-16
Shizuoka -0.154502 0.047311 -0.024293 -0.106965 -4.391609e-16
Aichi 0.032203 -0.861350 0.024752 0.083958 -3.969445e-16
Mie 0.688121 -0.134592 0.041857 0.025899 -1.808552e-16
Shiga 0.976152 -0.043429 0.004308 0.064238 -8.465224e-16
Kyoto 0.399057 -0.759579 -0.001051 0.106776 -7.035925e-16
Osaka -0.070228 -1.072591 0.053289 0.124451 -5.013381e-16
Hyogo 0.285716 -0.694121 0.046409 0.074852 -3.553832e-16
Nara 0.354718 -0.663109 0.020464 0.078267 -9.422215e-16
Wakayama 0.803013 -0.297697 0.065230 0.073463 -6.015682e-16
Tottori 1.122545 0.279755 0.028076 0.045588 -5.874166e-16
Shimane 1.079170 0.825695 -0.189601 -0.009561 -3.303743e-16
Okayama 0.552460 0.067643 0.022446 -0.027014 -5.810430e-16
Hiroshima 0.030436 -0.419868 0.024179 -0.011057 -1.522397e-16
Yamaguchi -0.260092 -0.137450 0.073770 -0.090442 -1.754969e-16
Tokushima 0.601511 -0.179480 0.040923 0.019526 -7.212218e-17
Kagawa 0.489876 -0.310648 0.031411 0.026189 -1.727164e-16
Ehime 0.243787 -0.197108 0.034806 -0.027773 -4.798676e-16
Kochi 0.419732 -0.297082 0.072960 0.011976 -5.649252e-16
Fukuoka -0.725140 -0.283917 0.034624 -0.090111 -2.988795e-16
Saga 0.469455 0.381240 -0.003591 -0.080336 -1.830035e-17
Nagasaki -0.760055 0.067560 0.052436 -0.149444 -4.453860e-16
Kumamoto -2.273080 -0.047393 0.017080 -0.075858 -1.269966e-16
Oita -1.734213 0.448740 0.144752 -0.190635 -3.334187e-16
Miyazaki -4.282241 0.738680 0.026392 0.226628 -3.211087e-17
Kagoshima -4.569257 0.657853 0.055128 0.322384 1.821382e-16
# 第一主成分と第二主成分でプロットする
plt.figure(figsize=(10, 10))
for x, y, name in zip(feature[:, 0], feature[:, 1], y_labels):
    plt.text(x, y, name, alpha=0.8, size=15)
plt.scatter(feature[:, 0], feature[:, 1], alpha=0.8)
plt.title("Principal Component Analysis")
plt.xlabel("The first principal component score")
plt.ylabel("The second principal component score")
plt.show()

output_31_0.png

上図を「図2」と呼ぶことにします。課題2と5で、似たような図を作成してもらいます。

列をエントリとし、行を説明変数とする場合。

# 表形式のデータを、PCAにかけられる形に整形する。
# 列をエントリとし、行を説明変数とする場合。
x_labels = []
y_labels = []
data2 = []
for i, line in enumerate(open('sake_dataJ.txt')):
    if i == 0:
        a = line.strip().split("\t")
        y_labels = []
        for j, val in enumerate(a):
            if j == 0:
                continue
            else:
                y_labels.append(val)
                data2.append([])
    else:
        a = line.strip().split("\t")
        b = []
        for j, val in enumerate(a):
            if j == 0:
                x_labels.append(val)
            else:
                data2[j - 1].append(float(val))
data2 = normalize2(data2)
#主成分分析の実行
pca = PCA()
pca.fit(data2)
PCA(copy=True, n_components=None, whiten=False)
# 因子負荷量の確認。左から順に第一変数、第二変数、、、
# 上から順に因子1、因子2、、、
pd.DataFrame(pca.components_, columns=x_labels)
Hokkaido Aomori Iwate Miyagi Akita Yamagata Fukushima Ibaraki Tochigi Gunma ... Kagawa Ehime Kochi Fukuoka Saga Nagasaki Kumamoto Oita Miyazaki Kagoshima
0 0.275489 0.039741 0.037039 -0.039969 -0.059777 -0.040114 -0.055869 0.000841 0.022621 0.091066 ... -0.016326 -0.017543 -0.014956 0.128462 0.008461 0.076744 0.233482 0.136635 0.306588 0.432275
1 -0.116942 0.040067 0.022673 0.024537 -0.008161 0.062057 -0.066715 -0.093032 -0.003837 -0.024243 ... 0.100946 0.024591 0.084554 -0.276205 0.068738 0.005495 -0.053999 0.027990 -0.025145 -0.120296
2 -0.046757 -0.028055 0.040584 0.060954 0.147034 0.100469 0.164137 0.094025 0.026149 0.056845 ... -0.050275 -0.029234 -0.057383 -0.037363 -0.007293 -0.041365 -0.130533 -0.056618 -0.114217 -0.159604
3 0.149324 0.223728 0.034813 0.428843 0.075589 0.152153 0.254214 -0.019647 -0.001778 -0.096611 ... -0.002780 -0.045749 0.013399 -0.059985 -0.036428 -0.002992 -0.148868 0.124259 -0.102680 -0.163846
4 -0.172858 -0.207267 -0.054197 -0.083138 -0.030749 0.071060 -0.057463 -0.006176 -0.013600 0.038431 ... -0.129569 0.279367 -0.017207 0.214137 -0.035018 -0.128023 -0.260437 -0.016798 0.032803 0.069383

5 rows × 46 columns

# それぞれの因子にどの説明変数がどの程度用いられているか図示する
plt.figure(figsize=(5, 5))
for x, y, name in zip(pca.components_[0], pca.components_[1], x_labels):
    plt.text(x, y, name, alpha=0.8, size=10)
plt.scatter(pca.components_[0], pca.components_[1])
plt.title("Factor loadings")
plt.xlabel("Factor 1")
plt.ylabel("Factor 2")
plt.show()

output_36_0.png

# 主成分に対する因子の寄与率を確認。左から順に第一主成分、第二主成分、、、
list(pca.explained_variance_ratio_)
[0.65580254639595692,
 0.22004551664752053,
 0.089448901881823112,
 0.034703035074699393,
 1.962690226154014e-32]
# 累積寄与率を図示する
import matplotlib.ticker as ticker
plt.gca().get_xaxis().set_major_locator(ticker.MaxNLocator(integer=True))
plt.plot([0] + list(np.cumsum(pca.explained_variance_ratio_)), "-o")
plt.xlabel("Number of principal components")
plt.ylabel("Cumulative contribution ratio")
plt.show()

output_38_0.png

# データを主成分空間に写像 = 次元圧縮
feature = pca.transform(data2)
# 次元圧縮後のデータ。左から順に第一主成分、第二主成分、、、
pd.DataFrame(feature, index=y_labels)
0 1 2 3 4
Sake -83.478816 -41.240646 38.205369 -3.137163 -9.606462e-15
Shochu 139.596385 -32.110658 6.807571 -1.155559 8.106997e-15
Bear -42.598445 -23.181311 -46.321043 -14.139350 -1.285136e-13
Wine 5.375823 77.307076 11.970727 -14.610832 -1.034849e-13
Whisky -18.894947 19.225538 -10.662626 33.042904 2.958189e-13
# 第一主成分と第二主成分でプロットする
#plt.figure(figsize=(10, 10))
for x, y, name in zip(feature[:, 0], feature[:, 1], y_labels):
    plt.text(x, y, name, alpha=0.8, size=15)
plt.scatter(feature[:, 0], feature[:, 1], alpha=0.8)
plt.show()

output_41_0.png

上図を「図3」と呼ぶことにします。課題3で、似たような図を作成してもらいます。


課題

新しいノートを開いて、以下の課題を解いてください。

  • 課題1:下記リンクのデータを用い、図1のような Scatter Matrix を描いてください。

    ここでは、以下の列を使います。
    * 'Student' : 学生のID番号
    * '50mRun' : 50m走
    * 'longjump': 走り幅跳び
    * 'handball': ハンドボール投げ
    * 'chinning': 懸垂
    * 'sidestep': 反復横跳び
    * 'vertump': 垂直跳び
    * 'back': 背筋力
    * 'grip': 握力(両手平均)
    * 'backward': 上体そらし
    * 'forward' : 立位体前屈
    * 'stepping': 踏み台昇降

  • 課題2:上記データの主成分分析を行ない、図2のような散布図を作成し、特徴的な成績を残している学生のIDを述べてください。また、その特徴についても考察してください。

  • 課題3:同様に、上記データの主成分分析を行ない、図3のような散布図を作成し、各項目(50m走など)間の関係について考察してください。

  • 課題4:下記リンクのデータを用い、図1のような Scatter Matrix を描いてください。

  • 課題5:上記データの主成分分析を行ない、図2のような散布図を作成し、分布の特徴について考察してください。

総合実験(Pythonプログラミング)4日間コース

本稿は「総合実験(Pythonプログラミング)4日間コース」シリーズ記事です。興味ある方は以下の記事も合わせてお読みください。

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?