読者です 読者をやめる 読者になる 読者になる

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

f:id:pppurple:20160617025448p:plain

何も指定しない場合、デフォルトでは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

f:id:pppurple:20160617032212p:plain

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

f:id:pppurple:20160627191853p:plain

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

f:id:pppurple:20160617032226p:plain

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

f:id:pppurple:20160617032322p:plain

複数キーでのマージ

下記の様な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

f:id:pppurple:20160618021209p:plain

複数キーで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

f:id:pppurple:20160618021302p:plain

列名の重複

下記の様にマージ後に同じ列名がある場合、自動的に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

f:id:pppurple:20160618021701p:plain

下記の様に明示的に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

f:id:pppurple:20160618021729p:plain

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

f:id:pppurple:20160618023438p:plain

これもデフォルトは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

f:id:pppurple:20160618023505p:plain

階層データのマージ

下記の様な階層的な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

f:id:pppurple:20160618024116p:plain

これもデフォルトは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

f:id:pppurple:20160618024211p:plain

下記の様に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

f:id:pppurple:20160618024309p:plain

これもデフォルトは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

f:id:pppurple:20160618024349p:plain

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

f:id:pppurple:20160618024521p:plain

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

f:id:pppurple:20160618024555p:plain

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

f:id:pppurple:20160618024603p:plain

下記の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

f:id:pppurple:20160618024659p:plain

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

f:id:pppurple:20160618024727p:plain

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

f:id:pppurple:20160618024733p:plain

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

f:id:pppurple:20160618024900p:plain

これは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

f:id:pppurple:20160618024934p:plain

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

f:id:pppurple:20160618025025p:plain

明示的にinnerを指定するとinner joinになります。

In [25]: pd.concat([s1, s4], axis=1, join='inner')
Out[25]:
   0  1
a  0  0
b  1  5

f:id:pppurple:20160618025050p:plain

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

f:id:pppurple:20160618025105p:plain

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

f:id:pppurple:20160618025216p:plain

ディクショナリを指定することも可能。
ディクショナリのキーが、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

終わり。

【参考】
Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理