データサイエンスのためのPython入門13〜DataFrameのフィルタ操作の基本(超重要)〜

こんにちは,米国データサイエンティストのかめ(@usdatascientist)です.

今回も前回に引き続き,DataFrameのフィルタ操作(filter)とindex操作を紹介していこうと思います!

フィルタ操作というのは,ある条件に合致するレコードだけ抽出する操作です.エクセルの「フィルタ」機能でできるやつですね.

フィルタ操作はDataFrameの操作で最も頻出かつ重要な操作の一つです.できるだけわかりやすく説明するので付いてきてください!

(超重要)DataFrameを特定の条件でフィルタ(filter)する

前回同様,タイタニックのデータを使います.

この891レコードのうち,例えば生存者のレコードだけに絞りたい時にフィルタ操作をします.

わかりやすく,Step By Stepに説明しますね.

まず,前回の記事で説明したように df['Survived'] でSeriesを取得します.Kaggleの説明ページをみるところ,0=死亡 1=生存 のようです.取り出したSeriesを==で条件を作ってみましょう!

すると,FalseとTrue(boolean)のSeriesが返ってきました.

このSeriesをfilterという変数に入れて,df[]に渡すと・・・

Survived==1のレコードのみに絞られています.

df[filterの条件]で,ある条件に該当したレコードだけが返ってきます.SQLでいうwhere句のようなものです.

以下のようなイメージです.

Trueのところだけフィルタが通ります.レコードのindexは保たれることに注意してください.また,元のDataFrameは上書きされません.

普通はいちいち変数にはいれず,

とすることの方が多いです.

生存者にはどういう特徴があるのか確認したいですよね? 生存者と全体の統計量を比べてみましょう.

統計量の確認には前回紹介した.describe()を使います.

本当はグラフで比較すべきですが,この辺りのグラフの描画については第25回あたりの記事が参考になると思います.

Ageのmeanをみると,生存者の方が若干若いですね.あと,Fareのmeanをみると,高い運賃を払っている人の方が生存していると言えそうです.理屈で考えると,子供やクラスが高い人から優先的に救命ボートに乗れたのだろうと仮説が立てられます.

ただ,これが両者を比較して,「本当にそう言えるのか」,「Ageの1.3年の差はたまたまじゃないのか?」という疑問はありますよね?(「統計的有意性」(statistical significance)と呼びます.)

これに対して答えを出せるのが統計学です.今後本ブログで統計学入門講座を書いていく予定なので楽しみにしていてください!!

他にも試しに色々なフィルタをしてみてみましょう.

  • 60才以上のレコードに絞る
  • 1stクラスのレコードに絞る
  • 女性のレコードに絞る

答えはこちら↓

同じように,.describe()でそれぞれの条件で絞ったときのSurvivedの統計量をみると面白いですよ.女性の生存率は高く,60才以上の生存率は低いです.

  • ()&() や ()|() を複数条件でフィルタ可能

例えば60才以上(Age>=60)の女性(Sex==’female’)や1stクラス(Pclass==1)もしくは10才未満(Age<10)のレコード などは以下のように各条件を括弧 () で囲んで & (アンパサンド)や | (パイプ)で繋ぎます

Pythonだとandやorを使って条件を作りますが,DataFrameのフィルタ操作では&と|であることに注意です.

  • ~ (スクィグル)をつけるとNOT演算でフィルタ可能
~ を条件の前につけると,条件の真偽が逆転します(NOT演算やinversionといいます.).どういうことかというと,例えば df[df['Sex']=='female'] で女性のみのレコードを表示していたのに対し, df[~(df['Sex']=='female')] とすると男性のみのレコードになります.

これは特に「値がbooleanのカラムでフィルタする時」によく使います.

以下のDataFrameを考えてみます.

めっちゃシンプルなDataFrameです.タイタニックデータではSurvivedが0か1になっていましたが,今回はBooleanです.

それでは,生存者だけフィルタしてみます.

ちゃんとフィルタされてますね!

実はこのSurvivedカラムはすでにBooleanなので,==True必要ないですよね?df[‘Survived’]がすでにBooleanのSeriesになるので以下のようにそのままフィルタできます.

Survived==Falseに絞りたい場合は, df[df['Survived'==False] なんてことする必要なく,以下のようにできるのです!

めっちゃスマートですよね. ~ はこのように,Booleanのカラムで使うケースが多いです.もちろん,普通にフィルタリングするときも使いますが.

indexを変更する

  • .reset_index()で再度indexを割り振る

先ほど説明した通り,フィルタを通したDataFrameのindexはもとのDataFrameのままです. .reset_index() をすることでindexを0から順に再度割り振ります.

新しいindexが振られ,もとのindexは「index」というカラムになっています.(ややこし!)

また,前回説明した .drop() 同様,もとの df は上書きされないので, df を更新したい場合は inplace=True もしくは df = df.reset_index() で再代入しましょう.

  • .set_index()で特定のカラムをindexにする

例えばNameをindexにしたければ以下のようにindexをセットできます.

.reset_index() 同様, inplace=True でもとのdfを上書けます.

DataFrameを色々いじっていると,indexを振り直したくなる場面は結構あります.indexをセットすることはあまりないかもしれませんが,合わせて覚えておきましょう!

まとめ

  • DataFrameのフィルタ操作はデータサイエンス再頻出操作の一つです.
  • df[条件のSeries]でフィルタ可能.indexはそのまま
  • ()&() や ()|() を複数条件でフィルタ可能⇨括弧を忘れずに!あとandとor出ないことに注意
  • ~ (スクィグル)をつけるとNOT演算でフィルタ可能⇨とくにBooleanのカラムでよく使う
  • .reset_index()で再度indexを割り振る
  • set_index()で特定のカラムをindexにする

特に今回のフィルタ操作の説明は全て超重要事項です.

データサイエンスをする上で何度も出てきます.自分で色々なフィルタを作って試してみてください.

それでは!

↓次回書きました.DataFrameの欠損値NaNの操作についてです.欠損値の扱いはデータサイエンス超重要テーマです.

データサイエンスのためのPython入門14〜DataFrameの欠損値NaNに対応する〜