Python
numpy
matplotlib
pandas
Kaggle

【kaggle】Titanicデータを用いたpythonによるデータ解析のお勉強メモ

日本語文字化け回避

import matplotlib
import matplotlib.pyplot as plt
font = {'family' : 'IPAexGothic'}
matplotlib.rc('font', **font)
要素の種類を取得
$ np.unique(data.Sex)
> array(['female', 'male'], dtype=object)

データの前処理

ラベルのエンコーディング
####手作業でエンコーディング####

# 要素の種類をuniqueで取得してenumerateで0から順に採番
# 最後にディクショナリをmapしてやればよい
$ class_mapping = {label:idx for idx, label in enumerate(np.unique(data.Sex))}
> {'female': 0, 'male': 1}
$ data.Sex=data.Sex.map(class_mapping)

####sklearnのライブラリを使用####
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
# 性別を0, 1に変換
sexEncode = le.fit_transform(data.Sex.values)
data.Sex = sexEncode
# 元の性別ラベルに戻す
data.Sex = le.inverse_transform(sexEncode)

簡単なグラフ描画

要素ごとの数を集計したい:value_counts()
# maleとfemaleの2種類のデータが存在。それぞれの要素数が知りたい
$ data.Sex.head(5)

0      male
1    female
2    female
3    female
4      male
Name: Sex, dtype: object

$ data.Sex.value_counts()

male      577
female    314
Name: Sex, dtype: int64

data.Sex.value_counts().plot(kind='bar')
# female:0, male:1だが、上記記述でプロットすると
#左側のグラフが'1'に、右側のグラフが'0'として表示されてしまう
# xticksでラベルをリネームするときは要素を間違えないように注意が必要
plt.xticks([0, 1], ['male', 'female'])
plt.show()

download.png

複数の要素を一つのヒストグラム上で扱う

【ポイント】
・複数の要素を同一ヒストグラムで扱うには、要素の異なるデータセットを分割する必要がある

性別毎年齢分布
splitAsSex = [] # 性別毎にデータセットを分割するためのリストを用意

# データセットを性別で分割
for i in [0, 1]: # 0:male, 1:female
    splitAsSex.append(data[data.Sex == i])

# 性別ごとの年齢カラムを取り出す
# female, maleのデータセットについて、Ageカラムを欠損値をdropしてtmpリストに格納
tmp = [i["Age"].dropna() for i in splitAsSex]

plt.xlabel("Age")
# label=,,,で凡例セット
plt.hist(tmp, histtype="barstacked", bins=10, rwidth=0.5, color=['pink', 'skyblue'], label=['female', 'male'])
plt.legend() #凡例表示
plt.show()

download-5.png

年齢別生存者分布
splitAsSurvived = []

# データセットを生存者で分割
for i in [0, 1]:
    splitAsSurvived.append(data[data.Survived == i])

# 年齢ごとの年齢を取り出す
tmp  = [i["Age"].dropna() for i in splitAsSurvived]
plt.xlabel("Age")
plt.hist(tmp, histtype="barstacked", bins=10, rwidth=0.5, color=['red', 'blue'], label=['not survived', 'survived'])
plt.legend()
plt.show()

download-1.png

下記は客室グレード別の生存者の分布グラフを描画したものである。上記と同様の方法でヒストグラムの積み重ねで描画できる。
しかしちょっとしたことだが、客室グレードの[1, 2, 3]の3パターンをx軸に表すためにxticksすると、グラフの棒と値の表記位置がずれてしまう。ヒストグラムは本来値の分布を表現するものなので、棒の位置とラベル位置がずれるのは致し方ない。

綺麗に描画することをを考えると、積み上げ棒グラフを使用した方が良いだろう。

客室グレード別生存者分布
splitAsSurvived = []

# データセットを生存者で分割
for i in [0, 1]:
    splitAsSurvived.append(data[data.Survived == i])    
tmp = [i['Pclass'] for i in splitAsSurvived]

fig = plt.figure(figsize=(10,4)) #グラフ描画領域サイズを指定


##ヒストグラムで描画##
fig.add_subplot(1, 2, 1)
plt.xlabel('Pclass')
plt.hist(tmp, histtype="barstacked", bins=3, rwidth=0.5, color=['red', 'blue'], label=['not survived', 'survived'])
plt.xticks([1,2,3], ['1','2','3']) #客室グレードに対応する軸にラベルをプロット。(ヒストグラムだから軸ラベルがずれてしまう)
plt.legend()
plt.title("plot with histgram")


##積み上げ棒グラフを使うと綺麗に描けた、、が面倒くさい##
fig.add_subplot(1, 2, 2)
notSurvived = [len(tmp[0][tmp[0]== i]) for i in [1, 2, 3]]
survived = [len(tmp[1][tmp[1]==i]) for i in [1, 2, 3]]
plt.bar([1, 2, 3], notSurvived, width=0.5,color='red', label='not survived')
plt.bar([1, 2, 3], survived, width=0.5, bottom=notSurvived, color='blue', label='survived')
plt.xticks([1,2,3], [1,2,3])
plt.xlabel('Pclass')
plt.legend()
plt.title("plot with bar")
plt.show()

download-2.png

その他グラフ描画tips

複数のグラフを並べる方法
from numpy.random import randn
fig=plt.figure() # plt.figure()はグラフ描画の様々なオプションを提供している

fig.add_subplot(2,2,1) # 2*2のレイアウトを生成し、1番目をセレクト
plt.plot(randn(50).cumsum()) #1番目のエリアにプロット

fig.add_subplot(2,2,2) # 2番目のエリアを選択
plt.plot(randn(50).cumsum(), 'k--')

fig.add_subplot(2,2,3)
plt.plot(randn(50).cumsum(), 'r*')

fig.add_subplot(2,2,4)
plt.plot(randn(50).cumsum(), 'g--') # 同じエリアに重ねて描画
plt.plot(randn(50).cumsum(), 'b--')
plt.plot(randn(50).cumsum(), 'm--')
plt.show()

download.png

決定領域のプロット
def plotDecisionRegions(X, y, classifier, test_idx=None, resolution=0.01):
    #マーカー、カラーマップの用意
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('lightgreen', 'blue', 'red', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    x1_min, x1_max = X[:, 0].min() -1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() -1, X[:, 1].max() + 1

    #グリッドポイント生成
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))

    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)

    ##軸の範囲
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    #サンプルをプロット
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.8, c=cmap(idx),
                   marker=markers[idx], label=cl)

    #テストサンプルを目立たせて表示
    if test_idx:
        X_test, y_test = X[test_idx, :], y[test_idx]
        plt.scatter(X_test[:, 0], X_test[:, 1], c='',
                   alpha=1.0, linewidths=1, marker='o',
                   s=55, label='test set')
SVMによる学習モデルを作成
from sklearn.svm import SVC
svm = SVC(kernel='rbf', random_state=0, gamma=0.2, C=50.0)
svm.fit(x_train, y_train)
予測データをcsvでアウトプット
import csv
with open ('predict_result.csv', 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerow(["PassengerId", "Survived"])
    for pid, survived in zip(id.astype(int), svmPredict.astype(int)):
        writer.writerow([pid, survived])
seabornライブラリによるグラフ描画
import seaborn as sns

#sns.pairplot(data.drop(['Name', 'SibSp', 'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'], axis=1))
iris = sns.load_dataset("iris")
titanic = sns.load_dataset("titanic")
sns.pairplot(iris, hue="species")
sns.plt.show()

download-3.png