LoginSignup
13
11

More than 1 year has passed since last update.

【入門者向け】機械学習前にデータ探索・可視化でデータを理解(pandasとmatplotlib)

Last updated at Posted at 2021-04-29

Pandasをたまに使っていたのですが、毎回ググって調べるのが苦痛になってきたため記事にまとめました。Kaggleを本格的にやろうとしていることがきっかけです。
結構色々書いたのですが、グラフ出力はパターンが多すぎるので良いと思ったものがあれば適宜追加予定です。

環境

記事「UbuntuにpyenvとvenvでPython開発環境構築」に書いた方法で環境構築をしています。記事「Windows PCで機械学習環境を作る方法まとめ」に書いている別方法でもいいと思います(少し古いので間違っている可能性などあり)。

種類 バージョン 内容
OS Ubuntu20.04.01 LTS 仮想で動かしています
pyenv 1.2.24 複数Python環境を使うことがあるのでpyenv使っています
Python 3.9.2 pyenv上でpython3.9.2を使っています
パッケージはvenvを使って管理しています

上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。

種類 バージョン
pandas 1.2.4
matplotlib 3.4.1
jupyter lab 3.0.14

前提

データはKaggle Titanicのtrain.csvを使っています。
各ライブラリのエイリアスは以下のように定義しています。

import pandas as pd 
import matplotlib.pyplot as plt

ファイル読込

read_csvを使います。特筆することもないですが、いろいろオプションがありますので公式APIを参照ください。read_tableもありますが、デフォルトの区切り文字が違うだけのようです(記事「pandasでcsv/tsvファイル読み込み(read_csv, read_table)」参照)。

train_data = pd.read_csv("/kaggle/input/titanic/train.csv")

read_tableread_csvは過去に言語処理100本ノックでも多用しました。

ファイル読込時にやること

概要出力: info

ファイル読込時にinfo関数で概要を出力します。型がわかったり、欠損値がわかったりと便利です。

train_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB

統計情報出力: describe

describe関数で数値系項目は統計情報を出力できます。

train_data.describe()

image.png

データ加工

コピー: copy

元データを保存しておきたい場合は、コピーして新しいDataFrameに対して加工します。

train_new = train_data.copy()

値のカウント: value_counts

value_countsを使って値の件数カウントをします。デフォルトでソートONなので、OFFにするオプションをよく使います。

print(train_data.Pclass.value_counts())
print('----')
print(train_data.Pclass.value_counts(sort=False))
3    491
1    216
2    184
Name: Pclass, dtype: int64
----
1    216
2    184
3    491
Name: Pclass, dtype: int64

文字列検索・抽出系

文字列検索・抽出はよくやると思うので、簡単に書いておきます。詳しくは、以下の2つの記事で書きました。

列に対して文字列部分一致検索

str.containtsを使って列に対して文字列部分一致検索をします。今回は使っていませんが、正規表現も使えます。
記事「ゼロから覚えるPython正規表現の基本とTips」に正規表現について以前まとめました。

# 文字列の部分一致検索
print(train_data[train_data.Name.str.contains('Mr.', regex=False)].Name)
0             Braund, Mr. Owen Harris
4            Allen, Mr. William Henry
5                    Moran, Mr. James
6             McCarthy, Mr. Timothy J
12     Saundercock, Mr. William Henry
                    ...              
881                Markun, Mr. Johann
883     Banfield, Mr. Frederick James
884            Sutehall, Mr. Henry Jr
889             Behr, Mr. Karl Howell
890               Dooley, Mr. Patrick
Name: Name, Length: 517, dtype: object

列に対して文字列部分一致検索での件数出力

リストに検索語句を個々に入れて、各検索語句でヒットした件数を出力します。

# 文字列部分一致で件数カウント
titles = ["Mr.", "Miss.", "Mrs.", "Master.", "Dr.", "Rev.", "Col.", "Ms.", 
          "Mlle.", "Mme.", "Capt.", "Countess.", "Major.", "Jonkheer.", "Don.", 
         "Dona.", "Sir.", "Lady."]
total = 0
for i, title in enumerate(titles):
    print(i, title, ": ", train_data.Name.str.contains(title, regex=False).sum())
    total += train_data.Name.str.contains(title, regex=False).sum()
    
print("Total: ", total)
出力結果
0 Mr. :  517
1 Miss. :  182
2 Mrs. :  125
3 Master. :  40
4 Dr. :  7
5 Rev. :  6
6 Col. :  2
7 Ms. :  1
8 Mlle. :  2
9 Mme. :  1
10 Capt. :  1
11 Countess. :  1
12 Major. :  2
13 Jonkheer. :  1
14 Don. :  1
15 Dona. :  0
16 Sir. :  1
17 Lady. :  1
Total:  891

列に対して文字列部分一致検索した結果を新しい列に追加

文字列検索した結果、合致した文字列をTitleという列に追加しています。

# 'Name'に'Titleリストの文字を含んでいた場合は列'Title'に設定
for title in titles:
    train_data.loc[train_data.Name.str.contains(title, regex=False), 'Title'] = title
    
print(train_data.loc[:,['Name', 'Title']])
出力結果
                                                  Name  Title
0                              Braund, Mr. Owen Harris    Mr.
1    Cumings, Mrs. John Bradley (Florence Briggs Th...   Mrs.
2                               Heikkinen, Miss. Laina  Miss.
3         Futrelle, Mrs. Jacques Heath (Lily May Peel)   Mrs.
4                             Allen, Mr. William Henry    Mr.
..                                                 ...    ...
886                              Montvila, Rev. Juozas   Rev.
887                       Graham, Miss. Margaret Edith  Miss.
888           Johnston, Miss. Catherine Helen "Carrie"  Miss.
889                              Behr, Mr. Karl Howell    Mr.
890                                Dooley, Mr. Patrick    Mr.

可視化

相関行列

corr関数を使って相関行列を出力します。無駄な行を省くために列名を指定しています。留意点です。

  • データ型がobject(文字列)は除外され、数値(int, float)型およびbool型(Trueが1、Falseが0)の相関係数が算出されます。
  • 相関係数算出方法のデフォルトはピアソンの積率相関係数
  • 欠損値NaNは計算から除外
  • matplotlibでグラフ化しているわけではない
  • stylebackground_gradientを使ってヒートマップっぽく表示することで見やすい

※参考記事「【1行で】Pandasだけで相関行列をヒートマップっぽく可視化する」

train_data.loc[:, 
["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"]].corr().style.background_gradient(axis=None)

image.png

グラフ

少量データはExcelでグラフ作ったりしたほうが早いのですが、慣れのためにライブラリmatplotlibでグラフ出力やってみます。
DataFrameの列を簡単に出力するだけなら1行で出来ます。この辺はPandasの素晴らしい点ですね。

train_data.Survived.value_counts(sort=False).plot.bar()

image.png

欠損値をグラフがどのように解釈するか注意が必要です

matplotlibの基本

簡易的な出力なら上記のコードだけでいいのですが、グリッドやラベル、グラフを並べるなど、いろいろしたくなります。そのときに基本を知っておく必要があります。
今まで、適当にググりながらグラフ表示してきた人は、記事「早く知っておきたかったmatplotlibの基礎知識、あるいは見た目の調整が捗るArtistの話」を読みましょう。2種類の流儀が世の中に混同されていますが、そこを整理してくれます。
あと、有名な日本語使用に関する豆腐問題は「豆腐(グラフ文字化け対応)対応」を参照ください。
細かい調整をしようと思ったら記事「matplotlibのめっちゃまとめ」が参考になります。

グラフの並列表示

ダッシュボードのようにグラフを並べて表示したくなることがあります。その場合はplt.subplots時に行数(nrows)・列数(ncols)と全体のサイズを指定します。ここで取得したaxesで個々のグラフに関する調整をします。
まずは、おまじないのように以下のコマンドを実行。

import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(12, 3))

すると2行・3列の空のグラフが出力されます。
image.png

ここで、エリア全体を司るfigを使えば、例えばグラフエリア間の余白長さを調整できます。私の乏しい経験ではあまり使いません。例えば、余白を調整してみます(わかりやすいようにあえて大きくしています)。

fig.subplots_adjust(wspace=3, hspace=3)

image.png

axesは配列です。個々のグラフを司ります。例えばX軸ラベルをset_xticklabelsで変えてみます(グラフ左下)。print(axes.shape)の出力は(2, 3)です(plt.subplotsで指定した行列数)。

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(12, 3))
print(axes.shape)
axes[1, 0].set_xticklabels(labels=['aaa', 'bbb'], rotation=30, horizontalalignment="center")

image.png

より柔軟な配置をする場合は以下のページが参考になります。

基本: 円グラフ

割合を見たい場合には円グラフですね。autopct="%1.1f%%とすることでデータラベルを%で小数点第1位まで出してくれます。value_counts時にソートをOFFにしているのは、ラベルとの整合性を保つためです(自動でラベル出力されるのですが、「0」と「1」だと意味がすぐにわからない
ので追加)。

位置 オプション
オプションなし
中央 ラベルあり
ラベル、割合データラベル(autpct)あり
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(12, 3))

fig.subplots_adjust(wspace=0.5, hspace=0.5)
labels_survived = ["0: Dead","1: Survived"]
train_data.Survived.value_counts(sort=False).plot.pie(ax=axes[0])
train_data.Survived.value_counts(sort=False).plot.pie(labels=labels_survived, ax=axes[1])
train_data.Survived.value_counts(sort=False).plot.pie(labels=labels_survived, autopct="%1.1f%%", ax=axes[2])
plt.show()

image.png

基本: 棒グラフ(積上でない)

棒グラフにset_xticklabelsでラベルを追加し、向きを傾けています。また、gridでY軸にグリッドを追加します。同じグラフの3つを並列で比較しています。
value_counts時にソートをOFFにしているのは、ラベルとの整合性を保つためです。
4列目のデータラベルを出力するコードは少しトリッキーです。text関数を使ってX座標とY座標を指定して主力しています(少し見にくい)。

位置 オプション
1列目 オプションなし
2列目 ラベルあり
3列目 ラベルあり、ラベル向き調整
4列目 ラベルあり、ラベル向き調整、データラベルあり

image.png

LABELS_SURVIVED = ['0: Dead', '1: Survived']
sr_survived = train_data.Survived.value_counts(sort=False)

fig, axes = plt.subplots(nrows=1, ncols=4, figsize=(16, 3))
fig.subplots_adjust(wspace=0.5, hspace=0.5)

sr_survived.plot.bar(ax=axes[0])
sr_survived.plot.bar(ax=axes[1])
sr_survived.plot.bar(ax=axes[2])
sr_survived.plot.bar(ax=axes[3])

axes[1].set_xticklabels(labels=LABELS_SURVIVED)
axes[1].grid(axis='y', linestyle='dotted')

axes[2].set_xticklabels(labels=LABELS_SURVIVED, rotation=30, horizontalalignment='center')
axes[2].grid(axis='y', linestyle='dotted')

axes[3].set_xticklabels(labels=LABELS_SURVIVED, rotation=30, horizontalalignment='center')
axes[3].grid(axis='y', linestyle='dotted')
# 2つのcountは順にy軸の座標と出力テキスト
[axes[3].text(i, count, count, horizontalalignment='center', color='green')
 for i, count in enumerate(sr_survived)]

plt.show()

基本: 棒グラフ(2種類データを積上含めて出力)

2種類のデータがあるので、ax.legendで凡例出力してわかりやすくします。

位置 オプション
1行目1列目 積上なしでデータ横並び
1行目2列目 積上なしでデータ横並びにしてデータラベル追加
2行目1列目 積上(stackedをTrue)
2行目2列目 積上(stackedをTrue)にしてデータラベル追加
2行目3列目 積上を100%表示(value_counts時にnormalizeをon)

image.png

def arrange_bar(ax, x_labels, y_labels=[]):
    ax.set_xticklabels(labels=x_labels, rotation=30, horizontalalignment="center")    
    hans, labs = ax.get_legend_handles_labels()
    ax.legend(handles=hans, labels=y_labels)
    ax.grid(axis='y', linestyle='dotted')

LABELS_SURVIVED = ['0: Dead', '1: Survived']
LABELS_PCLASS = ["1: 1st(Upper)", "2: 2nd(Middle)", "3: 3rd(Lower)"]
df_pclass = train_data.groupby(["Pclass"])["Survived"].value_counts(sort=False).unstack()
    
fig, axes = plt.subplots(nrows=1, ncols=4, figsize=(16, 3))
fig.subplots_adjust(wspace=0.5, hspace=0.5)

df_pclass.plot.bar(ax=axes[0])
df_pclass.plot.bar(ax=axes[1], stacked=True)
df_pclass.plot.bar(ax=axes[2], stacked=True)
train_data.groupby(["Pclass"])["Survived"].value_counts(sort=False, normalize=True).unstack().plot.bar(ax=axes[3], stacked=True)

arrange_bar(axes[0], LABELS_PCLASS, LABELS_SURVIVED)
arrange_bar(axes[1], LABELS_PCLASS, LABELS_SURVIVED)
arrange_bar(axes[2], LABELS_PCLASS, LABELS_SURVIVED)
[axes[2].text(i, item.sum(), item.sum(), horizontalalignment='center', color='green') 
 for i, (_, item) in enumerate(df_pclass.iterrows())]

arrange_bar(axes[3], LABELS_PCLASS, LABELS_SURVIVED)

plt.show()

実践

基本をもっと書こうかとも思ったのですが、時間ないので今は書きません(いつ書くかわからない)。実際にKaggle Titanic Challengeしたときのグラフ出力系コードです。
グラフ上に数値ではなくラベルを出したいので、以下のように辞書でラベルを定義。

# 今後も使うラベル
DICT_SURVIVED = {0: '0: Dead', 1: '1: Survived'}
DICT_PCLASS = {1: '1: 1st(Upper)', 2: '2: 2nd(Middle)', 3: '3: 3rd(Lower)'}
DICT_EMBARK = {'C': 'Cherbourg', 'Q': 'Queenstown', 'S': 'Southampton'}

円グラフと棒グラフの並列

生死をの数を単純に見たいときに円グラフと棒グラフを並べました。arrange_barはこの後でも使います。
タイタニック号の事件のことなどまるで知りませんでしたが、思ったより助かっているのですね。
image.png

# 棒グラフのX軸ラベルを回転させ、Y軸にグリッド追加
def arrange_bar(ax):
    ax.set_xticklabels(labels=ax.get_xticklabels(), 
                       rotation=30, # xラベルを回転(完全に縦だと見にくい)
                       horizontalalignment="center")
    ax.grid(axis='y', linestyle='dotted')  # Y軸グリッド追加

# 生死の数をカウントし、グラフでわかりやすいように名称変更
sr_survived = train_data['Survived'].value_counts().rename(DICT_SURVIVED)

fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(8, 3))
fig.subplots_adjust(wspace=0.5, hspace=0.5)
sr_survived.plot.pie(autopct="%1.1f%%", ax=axes[0])  # 円グラフ

sr_survived.plot.bar(ax=axes[1]) # 棒グラフ
arrange_bar(axes[1])
[axes[1].text(i, count, count, horizontalalignment='center') 
 for i, count in enumerate(sr_survived)]  # データラベル追加(x座標i, y座標countにcountを表示)

plt.show()

円グラフ・積上棒グラフ・積上でない棒グラフ・100%棒グラフ

円グラフ・積上棒グラフ・積上でない棒グラフ・100%棒グラフを並べます。
まずはコードから。積み上げでない棒グラフにデータラベルを出力する部分がトリッキーです。また、凡例がすでにテキストでわかりやすいやつはいいのですが、数字で「なんだっけ?」というやつは辞書で変換して出力しています。

def output_bars(column, index={}):
    
    fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 8))
    fig.subplots_adjust(wspace=0.5, hspace=0.5)    

    # 列の Value Count
    sr_vc = train_data[column].value_counts()
    
    # 列ごとの生死 Value Count
    df_vc = train_data.groupby([column])['Survived'].value_counts(sort=False).unstack()
    
    # 列ごとの生死 Value Count(標準化あり)
    df_vc_norm = train_data.groupby([column])['Survived'].value_counts(
        sort=False, normalize=True).unstack()
    
    # index(リネームする凡例)がない場合
    if len(index) == 0:
        df_vc.rename(columns=DICT_SURVIVED, inplace=True)
        df_vc_norm.rename(columns=DICT_SURVIVED, inplace=True)

        # index(リネームする凡例)がある場合
    else:
        sr_vc.rename(index, inplace=True)
        df_vc.rename(index=index, columns=DICT_SURVIVED, inplace=True)
        df_vc_norm.rename(index=index, columns=DICT_SURVIVED, inplace=True)

    sr_vc.plot.pie(ax=axes[0, 0], autopct="%1.1f%%")  # 円グラフ
    df_vc.plot.bar(ax=axes[0, 1], stacked=True) # 積上棒グラフ
    df_vc.plot.bar(ax=axes[1, 0]) # 棒グラフ
    df_vc_norm.plot.bar(ax=axes[1, 1], stacked=True) # 100%棒グラフ

    arrange_bar(axes[0, 1])
    arrange_bar(axes[1, 0])
    arrange_bar(axes[1, 1])

    # 積上棒グラフにデータラベル追加
    [axes[0, 1].text(i, item.sum(), item.sum(), horizontalalignment='center') 
     for i, (_, item) in enumerate(df_vc.iterrows())]
    
    # 棒グラフにデータラベル追加
    for rect in axes[1, 0].patches:
        height = rect.get_height()
    
        axes[1, 0].annotate('{:.0f}'.format(height),
                        xy=(rect.get_x() + rect.get_width() / 2, height),
                        xytext=(0, 3),  # 3 points vertical offset
                        textcoords="offset points",
                        ha='center', va='bottom')

    plt.show()
PClass(チケットクラス)

先程定義した関数output_barsを呼び出します。カテゴリ変数1, 2, 3だとわかりにくいので、辞書も渡します。
3(Lower)の安いチケットだと死にやすいのが一目瞭然ですね。

output_bars('Pclass', DICT_PCLASS)

image.png

Sex(性別)

今度は、テキストが入っている列「Sex」なのでラベル辞書は渡していません。
女性は8割弱助かっているのが興味深いです。レディファーストの精神で、救命ボートに先に乗せていったのでしょうか。

output_bars('Sex')

image.png

Embarked(出港地)

タイタニック号に乗った港です。乗った港によってなぜ生死の確率が左右するのかまるで理解できないです。

output_bars('Embarked', DICT_EMBARK)

image.png

箱ひげ図とヒストグラムの並列

数値系項目で分布をみたいときに箱ひげ図とヒストグラムで可視化しました。
ヒストグラムは、3行目に範囲を絞って見られるようにもしています。

# グラフで欠損値は自動除去されている
def output_box_hist(column, bins=20, query=None):
    
    # 3行目に範囲を絞ってヒスとグラムを出さない場合
    if query == None:
        fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 8))

    # 3行目に範囲を絞ってヒスとグラムを出す場合
    else:
        fig, axes = plt.subplots(nrows=3, ncols=2, figsize=(12, 12))
        
        train_data.query(query)[column].hist(ax=axes[2, 0], bins=bins) # 範囲限定ヒストグラム
        train_data.query(query).groupby('Survived')[column].plot.hist(
            ax=axes[2, 1], bins=bins, alpha=0.5, legend=True, grid=True) # 範囲限定ヒストグラム(生死別)
        axes[2, 1].legend(labels=[DICT_SURVIVED[int(float((text.get_text())))] 
                                  for text in axes[2, 1].get_legend().get_texts()]) # 凡例表示

    fig.subplots_adjust(wspace=0.5, hspace=0.5)

    train_data.boxplot(ax=axes[0, 0], column=[column]) # 箱ひげ図
    train_data.boxplot(ax=axes[0, 1], column=[column], by='Survived') # 箱ひげ図(生死別)
    axes[0, 1].set_xticklabels([DICT_SURVIVED[int(float(xticklabel.get_text()))] 
                                for xticklabel in axes[0, 1].get_xticklabels()]) # x軸にラベル表示
    train_data[column].hist(ax=axes[1, 0], bins=bins) # ヒストグラム
    train_data.groupby('Survived')[column].plot.hist(
        ax=axes[1, 1], bins=bins, alpha=0.5, grid=True, legend=True) #ヒストグラム
    axes[1, 1].legend(labels=[DICT_SURVIVED[int(float((text.get_text())))] 
                              for text in axes[1, 1].get_legend().get_texts()]) # ヒストグラム(生死別)

    plt.show()
Age(年齢)

年齢平均値は生死によって関係なさそうですが、15才以下だと生存確率が高いです。これも、女性は生存確率が高いのと同様、子供を優先的に助けたのでしょうか。

output_box_hist('Age')

image.png

Fare(運賃)

データが200以下に集中していたので、3行目に200以下のデータを出力しました。
安い料金を払っている人は死ぬ確率が非常に高いですね。貧乏人は粗末に扱われた、のでしょうか。

output_box_hist('Fare', 20, 'Fare < 200')

image.png

左右縦棒グラフとテーブル

種類が多いと横棒グラフはラベル出力の関係上、見にくくなります。そのため、縦棒グラフを出しました。

前処理

Titanicのファイル読み込みしたデータを加工します。この記事の本題と異なるのでスキップしてもらえれば。
上の方で書きましたが、名前からタイトル(Mrなど)を抜き出し、新しい列に設定します。その後に、タイトルごとに人数と死亡率のDataFrameを作ります。

# 'Name'に'Titleリストの文字を含んでいた場合は列'Title'に設定
for title in titles:
    train_data.loc[train_data.Name.str.contains(title, regex=False), 'Title'] = title
    
# Title出力用dfを作成し、トータルと死亡率計算
train_title = train_data.groupby(['Title'])['Survived'].value_counts().unstack().rename(columns=DICT_SURVIVED)
train_title = pd.concat([train_title, pd.DataFrame(train_title.sum(axis=1), columns=['Total'])], axis=1)
train_title['Death Rate'] = round(train_title['0: Dead'] / train_title['Total'], 2)
print(train_title)

タイトルごとの死亡率表示

縦棒グラフを左右にして表示。一番右の列にテーブルを表示します。1行目は総数で降順ソート、2行目は死亡率で降順ソート。
2行目のテーブルはソート順がグラフと完全に一致していません。「Death Rate」が同じ値だとうまくソート順がうまくいかず、何か方法があるのでしょうが、調べていません。
1行目の「Master」より下は数が少なすぎて、あまり機械学習に使えなそうです。「Master」は「少年ないし青年男性」の
ことのようです(スターウォーズのヨダみたいなイメージかと思っていたら違いました)。若年層は男性であってもそこそこ生存確率高いということですね。

image.png

def arrange_barh(ax, title):
    ax.set_ylabel('')
    ax.grid(axis='x', linestyle='dotted')
    ax.set_title(title)

def show_two_barh(axes, field, df):
    df.plot.barh(ax=axes[0], stacked=True, y=[0, 1])
    df['Death Rate'].plot.barh(ax=axes[1], color='green')
    axes[0].invert_xaxis()
    axes[0].set_yticklabels([])
    arrange_barh(axes[0], 'Total')
    arrange_barh(axes[1], 'Death Rate')

    axes[2].axis('tight')
    axes[2].axis('off')
    df.sort_values(field, ascending=False, inplace=True)
    axes[2].table(cellText=df.values,
                  colLabels=df.columns,
                  rowLabels=df.index, loc='center')

def output_barh(df, height):
    fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(18, height))
    fig.subplots_adjust(wspace=0.3, hspace=0.2)

    show_two_barh(axes[0], 'Total', df.sort_values('Total')) # 1行目はTotalでソート
    show_two_barh(axes[1], 'Death Rate', df.sort_values('Death Rate', na_position='first')) #2行目は死亡率でソート

    plt.show()

ある項目ごとのヒストグラム

タイトルごとの年齢ヒストグラムです。日本人に馴染みにくいタイトルの理解一助になりそうです。

image.png

_, ax = plt.subplots(figsize=(16, 15))
train_data.Age.hist(ax=ax, by=train_data['Title'])
plt.show()
13
11
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
13
11