Python で解析 11
“Advent Calendar 2013 - Python で解析!” の十一日目。DataFrame - 7
1. 前回の補足
今回は concat を取り上げるのだが、その前に、十日目の記事を読み返していたら、書き忘れていたことがあったので、先に補足しておく。
In [10]: df4 = df1.join([df2, df3]) In [11]: df4 Out[11]: 体重 名前 性別 身長 誕生日 好きなもの 3B005 79 山田 男 181 1982/02/02 ばなな 3B003 71 鈴木 男 173 1983/03/03 いちご 3B002 51 佐藤 女 159 1984/04/04 NaN 3B001 52 木村 女 164 NaN メロン
上の join の場合、'how' に 'left' を指定したのと同じになる。
In [12]: df1.join([df2, df3], how='left') Out[12]: 体重 名前 性別 身長 誕生日 好きなもの 3B005 79 山田 男 181 1982/02/02 ばなな 3B003 71 鈴木 男 173 1983/03/03 いちご 3B002 51 佐藤 女 159 1984/04/04 NaN 3B001 52 木村 女 164 NaN メロン
merge の場合の省略値は 'inner' だったが、join でも 'inner' を指定することができる。
In [13]: df1.join([df2, df3], how='inner') Out[13]: 体重 名前 性別 身長 誕生日 好きなもの 3B005 79 山田 男 181 1982/02/02 ばなな 3B003 71 鈴木 男 173 1983/03/03 いちご
'outer' も指定できる。
In [14]: df1.join([df2, df3], how='outer') Out[14]: 体重 名前 性別 身長 誕生日 好きなもの 3B001 52 木村 女 164 NaN メロン 3B002 51 佐藤 女 159 1984/04/04 NaN 3B003 71 鈴木 男 173 1983/03/03 いちご 3B004 NaN NaN NaN NaN 1981/01/01 りんご 3B005 79 山田 男 181 1982/02/02 ばなな
だが、 join で複数の DataFrame をつなぐ時には 'right' は指定できない。
In [15]: df1.join([df2, df3], how='right') (中略) ValueError: Only can inner (intersect) or outer (union) join the other axis
一つだけなら OK。
In [16]: df1.join(df2, how='right') Out[16]: 体重 名前 性別 身長 誕生日 3B004 NaN NaN NaN NaN 1981/01/01 3B005 79 山田 男 181 1982/02/02 3B003 71 鈴木 男 173 1983/03/03 3B002 51 佐藤 女 159 1984/04/04
2. では、 concat のための準備を
In [1]: import pandas as pd In [2]: df1 = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }, ...: index=['3B005', '3B003', '3B002', '3B001'] ...: ) In [3]: df2 = pd.DataFrame({ ...: u'名前': [u'田中', u'山田', u'鈴木', u'佐藤'], ...: u'誕生日': ['1981/01/01', '1982/02/02', '1983/03/03', '1984/04/04'] ...: }, ...: index=['3B004','3B005','3B003', '3B002'] ...: ) In [4]: df1 Out[4]: 体重 名前 性別 身長 3B005 79 山田 男 181 3B003 71 鈴木 男 173 3B002 51 佐藤 女 159 3B001 52 木村 女 164 In [5]: df2 Out[5]: 名前 誕生日 3B004 田中 1981/01/01 3B005 山田 1982/02/02 3B003 鈴木 1983/03/03 3B002 佐藤 1984/04/04
3. で、 concat を
merge や join は横につなぐイメージ (結合) だが、 concat は縦につなぐイメージ (連結)。通常の python の list + list のようなものだ。
In [6]: df3 = pd.concat([df1, df2]) In [7]: df3 Out[7]: 体重 名前 性別 誕生日 身長 3B005 79 山田 男 NaN 181 3B003 71 鈴木 男 NaN 173 3B002 51 佐藤 女 NaN 159 3B001 52 木村 女 NaN 164 3B004 NaN 田中 NaN 1981/01/01 NaN 3B005 NaN 山田 NaN 1982/02/02 NaN 3B003 NaN 鈴木 NaN 1983/03/03 NaN 3B002 NaN 佐藤 NaN 1984/04/04 NaN
レコードは単純に追加されるので、index が同じでも関係がなく、別のレコードして追加される。同じ名前のカラムは統合され、そうでないものは追加される。
In [8]: df3.columns Out[8]: Index([u'体重', u'名前', u'性別', u'誕生日', u'身長'], dtype=object) In [9]: df3.index Out[9]: Index([u'3B005', u'3B003', u'3B002', u'3B001', u'3B004', u'3B005', u'3B003', u'3B002'], dtype=object)
連結後は index が一意になってないことに注意。DataFrame の index は RDBMS のようにユニーク制約という訳ではないようだ。その代わりに (?)、ユニークかどうかをチェックすることができる。
In [10]: df3.index.is_unique Out[10]: False
今回はこんなところで。