
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)' の方がオブジェクト指向らしい書き方なのだが、軽く調べた限りではマイノリティーな感じ。データマイニングする人は、オブジェクト指向にこだわらない傾向があるのかもしれない。
今回はこんなところで。