PyData.Tokyoオーガナイザー 池内 孝啓(@iktakahiro)
株式会社ユーリエ https://eurie.co.jp CEO & Founder
Python, Go lang, Amazon Web Service
In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
np.seterr(invalid='ignore') # Workaround
Out[1]:
In [2]:
df = pd.read_csv("data/train.csv")
In [3]:
df[df.Age == 65][["Name", "Age"]]
Out[3]:
読み込んだデータを見てみましょう。各カラムにはラベルが付いており、このようなデータが存在します。
など
In [4]:
df.head(2)
Out[4]:
head()関数は引数に指定した行数分、先頭からデータを選択します。
In [5]:
df.tail()
Out[5]:
tail()関数は引数に指定した行数分、末尾からデータを選択します。head()関数もtail関数も、行数の指定を省略した場合、5行分のデータを選択します。
特定のカラムのみを指定してデータを抽出できます。
複数カラムの指定もできます。
In [6]:
df[['Name', 'Age', 'Sex']].head(3)
Out[6]:
In [7]:
df.describe()
Out[7]:
1つ1つのカラムをもう少し丁寧に見ていきましょう。
In [8]:
max_age = df['Age'].max()
print('年齢の最大値: {0}'.format(max_age))
mean_age = df['Age'].mean()
print('年齢の平均値: {0}'.format(mean_age))
データフレームの特定の列に対して、max()やmean()などの集計実行することが出来ます。
年齢の高い上位10名を確認してみましょう。
上位10名は全員男性のようですね。女性に限定してデータを見てみましょう。
In [9]:
df[df.Sex=='female'][['Name', 'Sex', 'Age']].sort_values(by='Age', ascending=False).head(10)
Out[9]:
更に詳しくPandasについて知りたい場合は、Pandasの作者であるWes Mckinney著 Pythonによるデータ分析入門――NumPy、pandasを使ったデータ処がオススメです。また、オンライン上でも、基本的な情報を網羅したチュートリアルがあります。
In [10]:
df['Cabin'].isnull().sum()
Out[10]:
Ticket(チケット番号)は、今回の分析では有用とは考えられません。
In [11]:
df[['Name', 'Ticket']].head()
Out[11]:
CabinとTicketのカラムは削除してしまいましょう。
In [12]:
df.drop(['Ticket', 'Cabin'], axis=1, inplace=True)
In [13]:
df.head()
Out[13]:
In [14]:
df.loc[4:10]
Out[14]:
Pandasには データの補間 を行うための interpolate()関数が存在します。
In [15]:
df.loc[4:6][['Name', 'Age']].interpolate()
Out[15]:
補間の手法が様々実装されていますが、デフォルトでは線型補間によりデータを補完します。ただし、今回のように並び順に意味のないデータの場合、この方法による補間は有効とは言えません。あくまで関数の紹介目的で解説しました。
次に、年齢の欠損値を、性別毎の年齢の平均値で補間してみます。
In [16]:
female_age_mean = round(df[df.Sex=='female']['Age'].mean())
male_age_mean = round(df[df.Sex=='male']['Age'].mean())
print('女性の平均年齢は{0}歳、男性は{1}歳です。この平均年齢で補間します。'.format(female_age_mean, male_age_mean))
In [17]:
round(df[df.Sex=='male']['Age'].mean())
Out[17]:
In [18]:
df[df.PassengerId==6][['PassengerId', 'Name', 'Sex', 'Age']]
Out[18]:
In [19]:
df_female = df[df.Sex=='female'].fillna({'Age': female_age_mean})
df_male = df[df.Sex=='male'].fillna({'Age': male_age_mean})
filled_df = df_female.append(df_male)
In [20]:
filled_df[filled_df.PassengerId==6][['PassengerId', 'Name', 'Sex', 'Age']]
Out[20]:
In [21]:
def classification_age(age):
if age <= 19:
return '1'
elif age <= 34:
return '2'
elif age <= 49:
return '3'
elif age >= 50:
return '4'
else:
return '0'
filled_df['AgeClass'] = filled_df.Age.map(classification_age)
filled_df.head()
Out[21]:
In [22]:
filled_df['Survived'].plot(alpha=0.6, kind='hist', bins=2)
plt.xlabel('Survived')
plt.ylabel('N')
Out[22]:
男性 / 女性の軸を加えてデータを見てみましょう。
In [23]:
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
for i, sex in enumerate(['male', 'female']):
filled_df['Survived'][filled_df.Sex==sex].hist(alpha=0.5, bins=2, ax=axes[i])
axes[i].set_title(sex)
fig.subplots_adjust(hspace=0.3)
fig.tight_layout()
男性よりも、女性のほうが生存率が高いことが分かります。ここに年齢を軸に加えます。
In [24]:
plt.hist([filled_df[(filled_df.Survived==0) & (filled_df.Sex=='male')]['Age'], filled_df[(filled_df.Survived==1) & (filled_df.Sex=='male')]['Age']],
alpha=0.6, range=(1,80), bins=10, stacked=True,
label=('Died', 'Survived'))
plt.legend()
plt.xlabel('Age')
plt.ylabel('N')
plt.title('male')
Out[24]:
In [25]:
plt.hist([filled_df[(filled_df.Survived==0) & (filled_df.Sex=='female')]['Age'],
filled_df[(filled_df.Survived==1) & (filled_df.Sex=='female')]['Age']],
alpha=0.6, range=(1,80), bins=10, stacked=True,
label=('Died', 'Survived'))
plt.legend()
plt.xlabel('Age')
plt.ylabel('N')
plt.title('female')
Out[25]:
In [26]:
fig = plt.figure(figsize=[15, 5])
ax1 = fig.add_subplot(121)
plt.hist([filled_df[(filled_df.Survived==0) & (filled_df.Sex=='female')]['Age'],
filled_df[(filled_df.Survived==1) & (filled_df.Sex=='female')]['Age']],
alpha=0.6, range=(1,80), bins=10, stacked=True,
label=('Died', 'Survived'))
plt.xlabel('Age')
plt.yticks([0, 40, 80, 120])
plt.ylabel('N')
plt.title('female')
plt.legend()
ax2 = fig.add_subplot(122)
plt.hist([filled_df[(filled_df.Survived==0) & (filled_df.Sex=='male')]['Age'],
filled_df[(filled_df.Survived==1) & (filled_df.Sex=='male')]['Age']],
alpha=0.6, range=(1,80), bins=10, stacked=True,
label=('Died', 'Survived'))
plt.xlabel('Age')
plt.yticks([0, 40, 80, 120])
plt.ylabel('N')
plt.title('male')
plt.legend()
plt.show()
最後に、Pclass(等級)の軸も加えて可視化してみましょう。
In [27]:
mean_age = df['Age'].mean()
for pclass in [1, 2, 3]:
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=[10, 10])
sex_n=0
for sex in ['male', 'female']:
for survived in [0, 1]:
fig = filled_df[((filled_df.Survived==survived) & (filled_df.Sex==sex) & (filled_df.Pclass==pclass) )].Age.hist(alpha=0.6, bins=10, ax=axes[sex_n][survived])
fig.set_xlabel("Age")
fig.set_ylabel('N ('+sex+str(survived)+' )')
axes[sex_n][survived].set_ylim(0,70)
fig.set_title('Pclass = {0} / mean_age = {1}'.format(pclass, round(mean_age)))
sex_n += 1
plt.subplots_adjust(hspace=0.5)
plt.show()