pandasの使い方(merge、join、concat編)
pandasのデータを結合する方法のメモです。
pandasのDataFrameとSeriesを
merge関数、join関数、concat関数で結合してみました。
目次
pandas
pandasの説明とインストール方法は下記を参照。
pppurple.hatenablog.com
IPythonで使ってみます。
SeriesとDataFrameを直接名前指定で使えるようにインポートして使います。
pandasはpdという省略名で使うのが通例です。
In [1]: from pandas import Series, DataFrame In [2]: import pandas as pd
merge関数
merge関数でDataFrameのマージをしてみます。
inner join
DataFrameを2つ定義します。
In [3]: df1 = DataFrame({'key': ['a', 'b', 'a', 'b', 'c', 'a'], ...: 'data1': range(6)}) In [9]: df2 = DataFrame({'key': ['a', 'b', 'd'], 'data2': range(3)}) In [6]: df1 Out[6]: data1 key 0 0 a 1 1 b 2 2 a 3 3 b 4 4 c 5 5 a In [11]: df2 Out[11]: data2 key 0 0 a 1 1 b 2 2 d
これらをmergeすると、共通の同じ列名(key)で結合されます。
In [10]: pd.merge(df1, df2) Out[10]: data1 key data2 0 0 a 0 1 2 a 0 2 5 a 0 3 1 b 1 4 3 b 1
何も指定しない場合、デフォルトではinner joinになります。
howで明示的にinnerを指定しても上記と同じになります。
In [21]: pd.merge(df1, df2, how='inner') Out[21]: data1 key data2 0 0 a 0 1 2 a 0 2 5 a 0 3 1 b 1 4 3 b 1
onでマージする列名を指定することもできます。
これも上記と同じになります。
In [12]: pd.merge(df1, df2, on='key') Out[12]: data1 key data2 0 0 a 0 1 2 a 0 2 5 a 0 3 1 b 1 4 3 b 1
下記の様に列名が異なるDataFrameを結合する場合。
In [15]: df3 = DataFrame({'key03': ['a', 'b', 'a', 'b', 'c', 'a'], 'data1': range(6)}) In [16]: df4 = DataFrame({'key04': ['a', 'b', 'd'], 'data2': range(3)}) In [17]: df3 Out[17]: data1 key03 0 0 a 1 1 b 2 2 a 3 3 b 4 4 c 5 5 a In [18]: df4 Out[18]: data2 key04 0 0 a 1 1 b 2 2 d
left_onとright_onでマージする列を指定します。
In [19]: pd.merge(df3, df4, left_on='key03', right_on='key04') Out[19]: data1 key03 data2 key04 0 0 a 0 a 1 2 a 0 a 2 5 a 0 a 3 1 b 1 b 4 3 b 1 b
left join
howにleftを指定すると左外部結合になります。
In [22]: pd.merge(df1, df2, how='left') Out[22]: data1 key data2 0 0 a 0 1 1 b 1 2 2 a 0 3 3 b 1 4 4 c NaN 5 5 a 0
right join
デフォルトではinner joinになっているため、
howにrightを指定すると右外部結合になります。
In [23]: pd.merge(df1, df2, how='right') Out[23]: data1 key data2 0 0 a 0 1 2 a 0 2 5 a 0 3 1 b 1 4 3 b 1 5 NaN d 2
outer join
howにouterを指定すると完全外部結合になります。
In [24]: pd.merge(df1, df2, how='outer') Out[24]: data1 key data2 0 0 a 0 1 2 a 0 2 5 a 0 3 1 b 1 4 3 b 1 5 4 c NaN 6 NaN d 2
複数キーでのマージ
下記の様なDataFrameで複数キーでマージする場合。
In [34]: df5 = DataFrame({'keyA': ['A', 'A', 'B'], 'keyB': ['one', 'two', 'two'], 'key5': range(1, 4)}) In [35]: df6 = DataFrame({'keyA': ['A', 'A', 'B', 'B'], 'keyB': ['one','one', 'two', 'two'], 'key6': range(4, 8)}) In [36]: df5 Out[36]: key5 keyA keyB 0 1 A one 1 2 A two 2 3 B two In [37]: df6 Out[37]: key6 keyA keyB 0 4 A one 1 5 A one 2 6 B two 3 7 B two
onに列名のリストを渡します。
この場合もデフォルトはinner joinになります。
In [38]: pd.merge(df5, df6, on=['keyA', 'keyB']) Out[38]: key5 keyA keyB key6 0 1 A one 4 1 1 A one 5 2 3 B two 6 3 3 B two 7
複数キーでouter joinにする場合、howで明示的に指定します。
In [39]: pd.merge(df5, df6, on=['keyA', 'keyB'], how='outer') Out[39]: key5 keyA keyB key6 0 1 A one 4 1 1 A one 5 2 2 A two NaN 3 3 B two 6 4 3 B two 7
列名の重複
下記の様にマージ後に同じ列名がある場合、自動的にsuffixが付きます。
下記の場合、KeyB列に_xと_yがついています。
In [40]: pd.merge(df5, df6, on='keyA') Out[40]: key5 keyA keyB_x key6 keyB_y 0 1 A one 4 one 1 1 A one 5 one 2 2 A two 4 one 3 2 A two 5 one 4 3 B two 6 two 5 3 B two 7 two
下記の様に明示的にsuffixを付けれます。
下記の場合、KeyB列に_5と_6が付いて分かりやすくなってます。
In [41]: pd.merge(df5, df6, on='keyA', suffixes=('_5', '_6')) Out[41]: key5 keyA keyB_5 key6 keyB_6 0 1 A one 4 one 1 1 A one 5 one 2 2 A two 4 one 3 2 A two 5 one 4 3 B two 6 two 5 3 B two 7 two
indexとのマージ
今までの例は、列同士の結合でしたが、
下記の様にDataFrameの列とindexをマージしたい場合。
In [42]: df1 Out[42]: data1 key 0 0 a 1 1 b 2 2 a 3 3 b 4 4 c 5 5 a In [43]: indkey = DataFrame({'val': [100, 200]}, index=['a', 'b']) In [44]: indkey Out[44]: val a 100 b 200
下記の様にright_index=Trueを指定する。
In [45]: pd.merge(df1, indkey, left_on='key', right_index=True) Out[45]: data1 key val 0 0 a 100 2 2 a 100 5 5 a 100 1 1 b 200 3 3 b 200
これもデフォルトはinner joinなので、howに明示的に指定することで、
outer joinにすることも可能。
In [46]: pd.merge(df1, indkey, left_on='key', right_index=True, how='outer') Out[46]: data1 key val 0 0 a 100 2 2 a 100 5 5 a 100 1 1 b 200 3 3 b 200 4 4 c NaN
階層データのマージ
下記の様な階層的なDataFrameをマージする場合。
In [52]: df1 = DataFrame({'key1': ['Apple', 'Apple', 'Apple', 'Orange', 'Orange'], 'price': [100, 200, 300, 200, 300], 'num': np.arange(5)}) In [54]: df2 = DataFrame(np.arange(12).reshape((6, 2)), index=[['Orange', 'Orange', 'Apple', 'Apple', 'Apple', 'Apple'], [200, 100, 100, 100, 200, 300]], columns=['shop1', 'shop2']) In [55]: df1 Out[55]: key1 num price 0 Apple 0 100 1 Apple 1 200 2 Apple 2 300 3 Orange 3 200 4 Orange 4 300 In [56]: df2 Out[56]: shop1 shop2 Orange 200 0 1 100 2 3 Apple 100 4 5 100 6 7 200 8 9 300 10 11
それぞれ結合する列名を指定します。
df1はリスト形式で列名を指定し、df2はindexで結合するのでright_indexにTrueを指定。
In [57]: pd.merge(df1, df2, left_on=['key1', 'price'], right_index=True) Out[57]: key1 num price shop1 shop2 0 Apple 0 100 4 5 0 Apple 0 100 6 7 1 Apple 1 200 8 9 2 Apple 2 300 10 11 3 Orange 3 200 0 1
これもデフォルトはinner joinなので、howに明示的に指定することで、
outer joinで結合することも可能。
In [58]: pd.merge(df1, df2, left_on=['key1', 'price'], right_index=True, how='outer') Out[58]: key1 num price shop1 shop2 0 Apple 0 100 4 5 0 Apple 0 100 6 7 1 Apple 1 200 8 9 2 Apple 2 300 10 11 3 Orange 3 200 0 1 4 Orange 4 300 NaN NaN 4 Orange NaN 100 2 3
下記の様にindex同士で結合したい場合。
In [62]: df1 = DataFrame(np.arange(6).reshape((3, 2)), index=['a', 'c', 'e'], columns=['shop1', 'shop2']) In [63]: df2 = DataFrame(np.arange(7, 15).reshape((4, 2)), index=['b', 'c', 'd', 'e'], ....: columns=['shop3', 'shop4']) In [64]: df1 Out[64]: shop1 shop2 a 0 1 c 2 3 e 4 5 In [65]: df2 Out[65]: shop3 shop4 b 7 8 c 9 10 d 11 12 e 13 14
left_indexとright_indexにTrueを指定する。
In [66]: pd.merge(df1, df2, left_index=True, right_index=True) Out[66]: shop1 shop2 shop3 shop4 c 2 3 9 10 e 4 5 13 14
これもデフォルトはinner joinなので、howに明示的に指定することで、
outer joinで結合することも可能。
In [67]: pd.merge(df1, df2, left_index=True, right_index=True, how='outer') Out[67]: shop1 shop2 shop3 shop4 a 0 1 NaN NaN b NaN NaN 7 8 c 2 3 9 10 d NaN NaN 11 12 e 4 5 13 14
join関数
join関数を使うと、列が重複していないDataFrameを簡単に結合できます。
注意点としては、join関数のデフォルトはleft joinになっていることです。
古いpandasのバージョンとの互換性のためらしいです。
In [68]: df1.join(df2) Out[68]: shop1 shop2 shop3 shop4 a 0 1 NaN NaN c 2 3 9 10 e 4 5 13 14
inner joinにしたい場合は、howで明示的に指定します。
In [69]: df1.join(df2, how='inner') Out[69]: shop1 shop2 shop3 shop4 c 2 3 9 10 e 4 5 13 14
outer joinにしたい場合。
In [70]: df1.join(df2, how='outer') Out[70]: shop1 shop2 shop3 shop4 a 0 1 NaN NaN b NaN NaN 7 8 c 2 3 9 10 d NaN NaN 11 12 e 4 5 13 14
下記のDataFrameを追加し、複数のDataFrameをjoinする場合。
In [71]: df3 = DataFrame(np.arange(9, 17).reshape((4, 2)), index=['a', 'b', 'e', 'f'], ....: columns=['shop5', 'shop6']) In [75]: df3 Out[75]: shop5 shop6 a 9 10 b 11 12 e 13 14 f 15 16
join関数にリスト形式で渡すと結合できます。
やはりデフォルトはleft joinになっています。
In [76]: df1.join([df2, df3]) Out[76]: shop1 shop2 shop3 shop4 shop5 shop6 a 0 1 NaN NaN 9 10 c 2 3 9 10 NaN NaN e 4 5 13 14 13 14
inner joinにしたい場合は、howで明示的に指定します。
In [77]: df1.join([df2, df3], how='inner') Out[77]: shop1 shop2 shop3 shop4 shop5 shop6 e 4 5 13 14 13 14
outer joinにしたい場合。
In [78]: df1.join([df2, df3], how='outer') Out[78]: shop1 shop2 shop3 shop4 shop5 shop6 a 0 1 NaN NaN 9 10 b NaN NaN 7 8 11 12 c 2 3 9 10 NaN NaN d NaN NaN 11 12 NaN NaN e 4 5 13 14 13 14 f NaN NaN NaN NaN 15 16
concat関数
concat関数でindexと値が連結できます。
In [11]: s1 = Series([0, 1], index=['a', 'b']) In [12]: s2 = Series([2, 3, 4], index=['c', 'd', 'e']) In [13]: s3 = Series([5, 6], index=['f', 'g']) In [14]: s1 Out[14]: a 0 b 1 dtype: int64 In [15]: s2 Out[15]: c 2 d 3 e 4 dtype: int64 In [16]: s3 Out[16]: f 5 g 6 dtype: int64
Seriesのリストを指定すると下記の様に連結されます。
デフォルトでは行で結合されます。
In [17]: pd.concat([s1, s2, s3]) Out[17]: a 0 b 1 c 2 d 3 e 4 f 5 g 6 dtype: int64
これはaxis=0を指定したのと同様です。
In [18]: pd.concat([s1, s2, s3], axis=0) Out[18]: a 0 b 1 c 2 d 3 e 4 f 5 g 6 dtype: int64
axis=1を指定すると列で結合されます。
In [19]: pd.concat([s1, s2, s3], axis=1) Out[19]: 0 1 2 a 0 NaN NaN b 1 NaN NaN c NaN 2 NaN d NaN 3 NaN e NaN 4 NaN f NaN NaN 5 g NaN NaN 6
join関数はデフォルトではouter joinになります。
In [22]: s4 Out[22]: a 0 b 5 f 5 g 6 dtype: int64 In [24]: pd.concat([s1, s4], axis=1) Out[24]: 0 1 a 0 0 b 1 5 f NaN 5 g NaN 6
明示的にinnerを指定するとinner joinになります。
In [25]: pd.concat([s1, s4], axis=1, join='inner') Out[25]: 0 1 a 0 0 b 1 5
join_axesでリストを渡すと、連結軸を指定することが可能。
下記では存在しないcとeが指定されてるので、結果はNaNとなります。
In [26]: pd.concat([s1, s4], axis=1, join_axes=[['a', 'c', 'b', 'e']]) Out[26]: 0 1 a 0 0 c NaN NaN b 1 5 e NaN NaN
DataFrameでも同様に連結可能。
In [32]: df1 = DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'], ....: columns=['one', 'two']) In [33]: df2 = DataFrame(np.arange(4).reshape(2, 2), index=['a', 'c'], columns=['three', 'four']) In [34]: df1 Out[34]: one two a 0 1 b 2 3 c 4 5 In [35]: df2 Out[35]: three four a 0 1 c 2 3
keysでリストを指定すると、DataFrameの列のヘッダになります。
In [36]: pd.concat([df1, df2], axis=1, keys=['001', '002']) Out[36]: 001 002 one two three four a 0 1 0 1 b 2 3 NaN NaN c 4 5 2 3
ディクショナリを指定することも可能。
ディクショナリのキーが、keysで指定したのと同様にヘッダになる。
In [37]: pd.concat({'001': df1, '002': df2}, axis=1) Out[37]: 001 002 one two three four a 0 1 0 1 b 2 3 NaN NaN c 4 5 2 3
終わり。