はじめに
この記事はPandasのクエリの備忘録的なものです。
大したことは書いてありません。
あしからず。
条件指定でクエリ
DataFrame.query("条件")みたいなやり方もあるけど、インデクシングでなんとかしたい。
米・ソ/露・欧・日・印・中の宇宙探査ミッションの整理を行ってたときに詰まったのでその例を使います。
import pandas as pd
mission_name = [(長いので省略)]
mission_year = [(同上)]
mission_destination = [(同上)]
mission_nation = ['USA']*73 + ['JP']*13 + ['Soviet/Russia']*82 + ['India']*2 + \
['China']*4 + ['ESA']*8
mission = pd.DataFrame({
'name': mission_name,
'year': mission_year,
'nation': mission_nation,
'destination': mission_destination
})
ミッション名、ミッションの年、打ち上げを行った国、目的地を入れた同じ長さのリストを作ってリストからDataFrameを作っています。
ここで、「打ち上げ国が'USA'のデータの打ち上げ年を取得したい」みたいになったら
mission[mission['nation'] == 'USA']['year']
と書きます。一個目のインデックス指定子[]
の中でmission['nation'] == 'USA'
となっていますがこの比較演算の返り値はbool型のpandas.Seriesになります。これをmission
データフレームのインデックスにしていすることでTrue
の部分だけが帰ってきます。このデータフレームに['year']
コラムのインデックスを指定することで所望のデータが取得できます。
条件指定が2つ以上になった時の注意点
条件指定が複数になった場合でも基本は同様なのですが少し注意が必要です。
例えば、「打ち上げ国が'USA'で目的地が'Moon'以外のデータの打ち上げ年を取得したい」と思った時に
mission[mission[mission['nation'] == 'USA']['destination'] != 'Moon']['year']
と書くと失敗します。
mission[mission['nation'] == 'USA']
で打ち上げ国がUSA
という条件指定をしたデータフレームを得ることができ、そのデータフレームに['destination'] != 'Moon'
と条件指定することで目的地が月以外という条件をつけたbool型のpandas.Seriesが得られます。
しかし、これをmissionのインデックスとすると失敗します。というのも、
mission[mission['nation'] == 'USA']['destination'] != 'Moon'
として得られたbool型のSeriesの長さはmission
データフレームのうち国名が'USA'にあてはまるデータ分でしかなく、missionのインデックスに使うには短くなってしまっているからです。
従って「打ち上げ国が'USA'で目的地が'Moon'以外のデータの打ち上げ年を取得したい」ならば以下のように記述する必要が有ります。
mission[mission['nation'] == 'USA'][mission[mission['nation'] == 'USA']['destination'] != 'Moon']['year']
頭が悪そうな書き方ですね。
追記
コメントにて以下の記法を教えていただきました、感謝。
「打ち上げ国が'USA'で目的地が'Moon'以外のデータの打ち上げ年を取得」したいならば、
bool型Seriesの二項演算
mission[(mission['nation'] == 'USA') & (mission['destination'] != 'Moon')['year']
またはpipeメソッド
mission['nation' == 'USA'].pipe(lambda df: df[df['destination'] != 'Moon'])['year']
と書けるようです。二項演算はインターセクションを求めてからインデックスに使う方法の様ですね。pipeメソッドはUnix系の|と同じ要領でしょうか。