このエントリーをはてなブックマークに追加

Advent Calendar 2013 - 9

Python で解析! - DataFrame 6

今回は DataFrame のマージについて。マージとは、二つのデータフレームを結合することで、SQL で言うところの join と同等のもので、数学的には集合演算とかベン図とか…を思い出してもらえればいいだろう。

1. データの準備

では、いつもの通りのデータの準備を。

import pandas as pd

df1 = pd.DataFrame({
   u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'],
   u'性別': [u'男', u'男', u'女', u'女'] ,
   u'身長': [181, 173, 159, 164],
   u'体重': [79, 71, 51, 52]
})

df2 = pd.DataFrame({
   u'名前': [u'田中', u'山田', u'鈴木', u'佐藤'],
   u'性別': [u'男', u'女', u'男', u'女'] ,
   u'誕生日': ['1981/01/01', '1982/02/02', '1983/03/03', '1984/04/04']
})
df1
   体重  名前 性別   身長
0  79  山田    181
1  71  鈴木    173
2  51  佐藤    159
3  52  木村    164

df2
   名前 性別         誕生日
0  田中    1981/01/01
1  山田    1982/02/02
2  鈴木    1983/03/03
3  佐藤    1984/04/04

今回はマージを取り扱うので、データは二つ用意する。誕生日のデータの方には、田中くんが増えていて、山田さんが女性になっていて、木村さんがいないという違いがある。そして、データの順番が一致していない。マージの振る舞いを確認するために、わざと少しばかりややこしくしている。

2. 何も考えずにマージ

やってみる。

pd.merge(df1, df2)
   体重  名前 性別   身長         誕生日
0  71  鈴木    173  1983/03/03
1  51  佐藤    159  1984/04/04

件数が少なくなってしまったが、表示されている各数値に間違いはないので、どうやらマージはできたようだ。

2. キーカラムを指定してマージ

Pandas の merge は、指定したそれぞれの DataFrame の同じカラム名をキーにしてマージする。なので、実は次のようにカラム名を指定したのと同じことなのだ。

pd.merge(df1, df2, on=[u'名前', u'性別'])
   体重  名前 性別   身長         誕生日
0  71  鈴木    173  1983/03/03
1  51  佐藤    159  1984/04/04

SQL もこのぐらい便宜を計らってほしいものだが…というのはさておき…。

試しに性別がキーに含まれないようにして、名前だけでマージすると次のようになる。

pd.merge(df1, df2, on=u'名前')
   体重  名前 性別_x   身長 性別_y         誕生日
0  79  山田      181      1982/02/02
1  71  鈴木      173      1983/03/03
2  51  佐藤      159      1984/04/04

性別が一致しなくても、名前だけで一致すればいいので、山田氏のレコードが増えた。その一方で、性別項目が二つできている。性別のサフィックスの '_x' が左に書いた df1 のもので、'_y' が右に書いた df2 のもの。

3. レコード数の差異を制御

df1 と df2 が完全に一致してないので、それをどう取り扱うかを制御してみる。SQL で言うところの left join とか outer join とか…のことだ。

最初の例では 2 件になってしまったが、それは両方に存在するレコードのみが抽出されたからで、以下と同等。

pd.merge(df1, df2, how='inner')
   体重  名前 性別   身長         誕生日
0  71  鈴木    173  1983/03/03
1  51  佐藤    159  1984/04/04

左側 (すなわち df1) さえあれば、右側 (すなわち df2) がなくてもかまわないなら、次のように書く。

pd.merge(df1, df2, how='left')
   体重  名前 性別   身長         誕生日
0  79  山田    181         NaN
1  71  鈴木    173  1983/03/03
2  51  佐藤    159  1984/04/04
3  52  木村    164         NaN

逆に左側がなくても、右側さえあれば良いなら、次のように書く。

pd.merge(df1, df2, how='right')
   体重  名前 性別   身長         誕生日
0  71  鈴木    173  1983/03/03
1  51  佐藤    159  1984/04/04
2 NaN  田中    NaN  1981/01/01
3 NaN  山田    NaN  1982/02/02

どちらか片方にさえあれば有効とするなら、how に 'outer' を指定する。

pd.merge(df1, df2, how='outer')
   体重  名前 性別   身長         誕生日
0  79  山田    181         NaN
1  71  鈴木    173  1983/03/03
2  51  佐藤    159  1984/04/04
3  52  木村    164         NaN
4 NaN  田中    NaN  1981/01/01
5 NaN  山田    NaN  1982/02/02

これが最大件数になる。

いずれの例でも同じく、データが存在しないところは NaN (Not a Number) となる。

なお、ここまでの例で 'pd.mege(df1, df2)' としているが、'df1.merge(df2)' のように書くことともできる。今回の説明の on や how の意味も同じように使える。'df1.merge(df2)' の方がオブジェクト指向らしい書き方なのだが、軽く調べた限りではマイノリティーな感じ。データマイニングする人は、オブジェクト指向にこだわらない傾向があるのかもしれない。

今回はこんなところで。