天色グラフィティ

機械学習やプログラミングでいろいろ作って遊ぶブログ

Kaggleで使えるpandasテクニック集

f:id:ejinote:20190112195735j:plain

PythonでKaggleなどのデータ分析を行う際、pandasでゴリゴリ作業をすることが多いかと思います。

最近知って「めっちゃ便利やん!」ってなったものをまとめておきたいと思います。 全部の関数にドキュメントへのリンクを付けたので参考にしてください。

今回も検証にはTitanicのデータセットを用います。また、文中でのdf.hoge()はpandasのDataFrameのメソッドであることを、pd.hoge()はpandasの関数であることを表します。

df = read_csv('input/train.csv', index_col=0)
print(df.shape)
df.head()

f:id:ejinote:20180530220813p:plain

最低限押さえておきたいやつら

まずはここから。

よく使うやつら。詳しい解説は省略するので、ドキュメントのリンク先を見てください。

関数 内容 リンク
df.describe() 最大最小、平均など基本統計量の表示 doc
df.head() df.tail() 先頭/末尾のn行を取る doc
df.values numpyのarrayで取り出す doc
df.isnull() df.notnull() NaNかどうか判定 doc
df.apply() df.map() 各行に処理をする doc
series.plot.hoge() プロットいろいろ doc

複雑な条件に該当する行を取る

  • df.query() doc

SQL-likeなクエリ文を利用することで該当する行を取得します。

Pclassが1で、30歳以上の人を表示してみます。

new = df.query("Pclass==1 and Age >= 30")
print(new.shape)
new.head()

f:id:ejinote:20180530220920p:plain

クエリ文の中では列名がそのまま変数として使えるほか、変数名の先頭に@をつけることで外部の変数も利用することができます。

列名の一部で列を選ぶ

  • df.filter() doc

regex='hoge'正規表現も使えます。列名のネーミングが統一されているDataFrameに対しては絶大な力を発揮します。 自分で列名をつけるときには適切な接頭辞・接尾辞などを使って良いネーミングをするよう心がけておきましょう。

列名がPで始まる列を取得してみます。(なんじゃそりゃ)

new = df.filter(regex='^P')
print(new.shape)
new.head()

特定の型の列だけを取ってくる

  • df.select_dtypes() doc

Kaggleだと変数がintだったりfloatだったりbooleanだったり文字列だったりするので、文字列だけ取って来るときなどに使えます。

文字列はDataFrame内ではobjectという型で扱われています。 整数・小数・真偽値以外はすべてobjectになってしまいますが、Kaggleのようにcsvから読み込む場合はobjectなら文字列と思って良いでしょう。

new = df.select_dtypes(['object'])
print(new.shape)
new.head()

f:id:ejinote:20180530223549p:plain

文字列の列だけ取れていることが分かります。

文字列の列名を取得する場合はこんな感じでしょうか。

# 愚直な方法
cat_cols = [f for f in df.columns if df[f].dtype == 'object']

# select_dtypesを使った場合
cat_cols = df.select_dtypes(['object']).columns

excludeを利用して、特定の型を除くこともできます。

new = df.select_dtypes(exclude=np.float)
print(new.shape)
new.head()

f:id:ejinote:20180530223534p:plain

分類ごとに数える・集計する

  • df.groupby()['hoge'].value_counts().unstack() doc
  • df.pivot_table() doc

df.groupby()['hoge'].value_counts().unstack()は行にする変数Aと列にする変数Bを選び、Aでグループを作ってBの種類ごとに集計することができます。

Pclass(船室等級)でグループを作り、Survivedの値を種類ごとに集計してみます。

df.groupby('Pclass')['Survived'].value_counts().unstack()

df.pivot_table()はより一般化し、2つの変数A, Bに着目して別の変数Cを集計することができます。

性別とPclass(船室等級)について、生存率を集計してみましょう。

df.pivot_table(index='Sex', columns='Pclass', values='Survived', aggfunc=np.mean)

……これは悲惨ですね。1等2等船室の女性は90%以上生き残るのに、2等3等船室の男性は10%そこそこしか生き残らないという。

プログレスバーを表示する

各行に処理を行いたい場合はdf.apply()df.map()を使いますが、tqdmというライブラリを使うことでプログレスバーを表示することができます。

名前から称号(Mr.とかMrs.とか)を取り出す処理を書いてみます。

from tqdm import tqdm
tqdm.pandas()

df['Title'] = df.progress_apply(lambda x: x['Name'].split()[1], axis=1)
df.head().iloc[:, -5:]

プログレスバーが出るので、行数が多い場合でも固まってるんじゃ?という心配をせずに済みます。

さいごに

pandasの便利機能や、こういう処理がしたい場合の賢い書き方、みたいなものがあればTwitterやコメントでぜひ教えてください!

Kaggle、がんばっていきましょう! (現在行われているHome Creditコンペが面白いです)

前回の記事:

amalog.hateblo.jp