【Pandas】DataFrameを結合する方法 | concat / merge / join

## 【はじめに】

Pythonライブラリの「Pandas」の中で、DataFrameを結合する方法はいくつかあります。
今回はその中でも「concat」、「merge」、「join」について、それぞれの違いに触れながら紹介していきます。

### 本記事の内容

- pandasのインポート
- csvファイルの読み込み
- 列を取得する
- DataFrameを結合する | concat()
- DataFrameを結合する | merge()
- DataFrameを結合する | join()


## 【pandasのインポート】

```Python
import pandas as pd
```

## 【csvファイルの読み込み】

「1920年から2015年までの全国の人口推移のデータ」を使用します。

```Python
df = pd.read_csv('data.csv', encoding='shift-jis')
df
```

|                      | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| -------------------- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 0                    | 1              | 北海道     | 大正 | 9          | 1920       | 2359183      | 1244322    | 1114861    | 
| 1                    | 2              | 青森県     | 大正 | 9          | 1920       | 756454       | 381293     | 375161     | 
| 2                    | 3              | 岩手県     | 大正 | 9          | 1920       | 845540       | 421069     | 424471     | 
| 3                    | 4              | 宮城県     | 大正 | 9          | 1920       | 961768       | 485309     | 476459     | 
| 4                    | 5              | 秋田県     | 大正 | 9          | 1920       | 898537       | 453682     | 444855     | 
| ...                  | ...            | ...        | ...  | ...        | ...        | ...          | ...        | ...        | 
| 934                  | 43             | 熊本県     | 平成 | 27         | 2015       | 1786170      | 841046     | 945124     | 
| 935                  | 44             | 大分県     | 平成 | 27         | 2015       | 1166338      | 551932     | 614406     | 
| 936                  | 45             | 宮崎県     | 平成 | 27         | 2015       | 1104069      | 519242     | 584827     | 
| 937                  | 46             | 鹿児島県   | 平成 | 27         | 2015       | 1648177      | 773061     | 875116     | 
| 938                  | 47             | 沖縄県     | 平成 | 27         | 2015       | 1433566      | 704619     | 728947     | 
| 939 rows × 8 columns |                |            |      |            |            |              |            |            | 


私のGitHubに「nikkei.csv」としてアップロードしてあるので、下記コマンドでダウンロードすれば簡単に準備できます。

```Shell
curl https://raw.githubusercontent.com/nakachan-ing/python-references/master/Pandas/data.csv -O
```

## 【列を取得する】
例として、

- 「都道府県コード、都道府県名、元号、和暦（年）、西暦（年）」のデータ
- 「人口（総数）、人口（男）、人口（女）」のデータ
- 「大正、昭和（平成以外）」のデータ（平成以外）
- 「平成」のデータ

それぞれのデータに分けて、新しくデータフレームを作成します。

```Python
df_1 = df[['都道府県コード', '都道府県名', '元号', '和暦（年）','西暦（年）']]
df_1.head()
```

|     | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 
| --- | -------------- | ---------- | ---- | ---------- | ---------- | 
| 0   | 1              | 北海道     | 大正 | 9          | 1920       | 
| 1   | 2              | 青森県     | 大正 | 9          | 1920       | 
| 2   | 3              | 岩手県     | 大正 | 9          | 1920       | 
| 3   | 4              | 宮城県     | 大正 | 9          | 1920       | 
| 4   | 5              | 秋田県     | 大正 | 9          | 1920       | 


```Python
df_2 = df[['人口（総数）', '人口（男）', '人口（女）']]
df_2.head()
```

|     | 人口（総数） | 人口（男） | 人口（女） | 
| --- | ------------ | ---------- | ---------- | 
| 0   | 2359183      | 1244322    | 1114861    | 
| 1   | 756454       | 381293     | 375161     | 
| 2   | 845540       | 421069     | 424471     | 
| 3   | 961768       | 485309     | 476459     | 
| 4   | 898537       | 453682     | 444855     | 

```Python
df_3 = df[df['元号']!='平成']
df_3.tail()
```

|     | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| --- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 652 | 43             | 熊本県     | 昭和 | 60         | 1985       | 1837747      | 872932     | 964815     | 
| 653 | 44             | 大分県     | 昭和 | 60         | 1985       | 1250214      | 593014     | 657200     | 
| 654 | 45             | 宮崎県     | 昭和 | 60         | 1985       | 1175543      | 558355     | 617188     | 
| 655 | 46             | 鹿児島県   | 昭和 | 60         | 1985       | 1819270      | 856493     | 962777     | 
| 656 | 47             | 沖縄県     | 昭和 | 60         | 1985       | 1179097      | 581102     | 597995     | 

```Python
df_4 = df[df['元号']=='平成']
df_4.head()
```

|     | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| --- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 652 | 43             | 熊本県     | 昭和 | 60         | 1985       | 1837747      | 872932     | 964815     | 
| 653 | 44             | 大分県     | 昭和 | 60         | 1985       | 1250214      | 593014     | 657200     | 
| 654 | 45             | 宮崎県     | 昭和 | 60         | 1985       | 1175543      | 558355     | 617188     | 
| 655 | 46             | 鹿児島県   | 昭和 | 60         | 1985       | 1819270      | 856493     | 962777     | 
| 656 | 47             | 沖縄県     | 昭和 | 60         | 1985       | 1179097      | 581102     | 597995     | 


**ポイント**

- 条件に合う列の値を取得する場合は、`DataFrame['カラム名']=='条件'`
- 条件以外の列の値を取得する場合は、`DataFrame['カラム名']!='条件'`
- 条件の値より大きい値を取得する場合は、`DataFrame['カラム名']>'条件'`
- 条件の値より小さい値を取得する場合は、`DataFrame['カラム名']<'条件'`

## 【DataFrameを結合する | concat()】

- `pd.concat()`関数では括弧内に結合したいpandas.DataFrameもしくはpandas.Seriesを角括弧[]で指定します。
- 列方向に結合したい場合は、`axis`オプションに「1」を指定します。

```Python
pd.concat([df_1, df_2], axis=1)
```

|                      | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| -------------------- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 0                    | 1              | 北海道     | 大正 | 9          | 1920       | 2359183      | 1244322    | 1114861    | 
| 1                    | 2              | 青森県     | 大正 | 9          | 1920       | 756454       | 381293     | 375161     | 
| 2                    | 3              | 岩手県     | 大正 | 9          | 1920       | 845540       | 421069     | 424471     | 
| 3                    | 4              | 宮城県     | 大正 | 9          | 1920       | 961768       | 485309     | 476459     | 
| 4                    | 5              | 秋田県     | 大正 | 9          | 1920       | 898537       | 453682     | 444855     | 
| ...                  | ...            | ...        | ...  | ...        | ...        | ...          | ...        | ...        | 
| 934                  | 43             | 熊本県     | 平成 | 27         | 2015       | 1786170      | 841046     | 945124     | 
| 935                  | 44             | 大分県     | 平成 | 27         | 2015       | 1166338      | 551932     | 614406     | 
| 936                  | 45             | 宮崎県     | 平成 | 27         | 2015       | 1104069      | 519242     | 584827     | 
| 937                  | 46             | 鹿児島県   | 平成 | 27         | 2015       | 1648177      | 773061     | 875116     | 
| 938                  | 47             | 沖縄県     | 平成 | 27         | 2015       | 1433566      | 704619     | 728947     | 
| 939 rows × 8 columns |                |            |      |            |            |              |            |            | 

- 行方向に結合したい場合は、`axis`オプションに「0」を指定します。

```Python
pd.concat([df_3, df_4], axis=0)
```
|                      | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| -------------------- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 0                    | 1              | 北海道     | 大正 | 9          | 1920       | 2359183      | 1244322    | 1114861    | 
| 1                    | 2              | 青森県     | 大正 | 9          | 1920       | 756454       | 381293     | 375161     | 
| 2                    | 3              | 岩手県     | 大正 | 9          | 1920       | 845540       | 421069     | 424471     | 
| 3                    | 4              | 宮城県     | 大正 | 9          | 1920       | 961768       | 485309     | 476459     | 
| 4                    | 5              | 秋田県     | 大正 | 9          | 1920       | 898537       | 453682     | 444855     | 
| ...                  | ...            | ...        | ...  | ...        | ...        | ...          | ...        | ...        | 
| 934                  | 43             | 熊本県     | 平成 | 27         | 2015       | 1786170      | 841046     | 945124     | 
| 935                  | 44             | 大分県     | 平成 | 27         | 2015       | 1166338      | 551932     | 614406     | 
| 936                  | 45             | 宮崎県     | 平成 | 27         | 2015       | 1104069      | 519242     | 584827     | 
| 937                  | 46             | 鹿児島県   | 平成 | 27         | 2015       | 1648177      | 773061     | 875116     | 
| 938                  | 47             | 沖縄県     | 平成 | 27         | 2015       | 1433566      | 704619     | 728947     | 
| 939 rows × 8 columns |                |            |      |            |            |              |            |            | 


## 【DataFrameを結合する | merge()】

- `pd.merge()`関数では括弧内に第一引数leftと第二引数rightに結合する2つのpandas.DataFrameを指定します。
- 結合するDataFrameに重複した列が存在する場合に使用します。

```Python
df_5 = df[['都道府県コード', '都道府県名', '元号', '和暦（年）','西暦（年）', '人口（総数）']]
df_5.head()
```

|     | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 
| --- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | 
| 0   | 1              | 北海道     | 大正 | 9          | 1920       | 2359183      | 
| 1   | 2              | 青森県     | 大正 | 9          | 1920       | 756454       | 
| 2   | 3              | 岩手県     | 大正 | 9          | 1920       | 845540       | 
| 3   | 4              | 宮城県     | 大正 | 9          | 1920       | 961768       | 
| 4   | 5              | 秋田県     | 大正 | 9          | 1920       | 898537       | 


```Python
df_2 = df[['人口（総数）', '人口（男）', '人口（女）']]
df_2.head()
```

|     | 人口（総数） | 人口（男） | 人口（女） | 
| --- | ------------ | ---------- | ---------- | 
| 0   | 2359183      | 1244322    | 1114861    | 
| 1   | 756454       | 381293     | 375161     | 
| 2   | 845540       | 421069     | 424471     | 
| 3   | 961768       | 485309     | 476459     | 
| 4   | 898537       | 453682     | 444855     | 


```Python
# df_5とdf_2で重複している「人口（総数）」の列をまとめて結合
_df = pd.merge(df_5, df_2)
_df
```

|                      | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| -------------------- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 0                    | 1              | 北海道     | 大正 | 9          | 1920       | 2359183      | 1244322    | 1114861    | 
| 1                    | 2              | 青森県     | 大正 | 9          | 1920       | 756454       | 381293     | 375161     | 
| 2                    | 3              | 岩手県     | 大正 | 9          | 1920       | 845540       | 421069     | 424471     | 
| 3                    | 4              | 宮城県     | 大正 | 9          | 1920       | 961768       | 485309     | 476459     | 
| 4                    | 5              | 秋田県     | 大正 | 9          | 1920       | 898537       | 453682     | 444855     | 
| ...                  | ...            | ...        | ...  | ...        | ...        | ...          | ...        | ...        | 
| 936                  | 43             | 熊本県     | 平成 | 27         | 2015       | 1786170      | 841046     | 945124     | 
| 937                  | 44             | 大分県     | 平成 | 27         | 2015       | 1166338      | 551932     | 614406     | 
| 938                  | 45             | 宮崎県     | 平成 | 27         | 2015       | 1104069      | 519242     | 584827     | 
| 939                  | 46             | 鹿児島県   | 平成 | 27         | 2015       | 1648177      | 773061     | 875116     | 
| 940                  | 47             | 沖縄県     | 平成 | 27         | 2015       | 1433566      | 704619     | 728947     | 
| 941 rows × 8 columns |                |            |      |            |            |              |            |            | 


**ポイント**
 
 `pd.merge()`関数を使用すると行数が増えることがあります。

今回は939行だったデータから941行に増えています。

人口（総数）をキーにしてデータを結合していますが、df_5に同じ人口（総数）「832832」が複数含まれていました。

この場合df_2の人口（総数）「832832」に対して、すべてのパターンで結合するためデータ行が増えることになリます。

```Python
df_5[df_5['人口（総数）']==832832]
```

|     | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 
| --- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | 
| 628 | 19             | 山梨県     | 昭和 | 60         | 1985       | 832832       | 
| 932 | 41             | 佐賀県     | 平成 | 27         | 2015       | 832832       | 

```Python
df_2[df_2['人口（総数）']==832832]
```

|     | 人口（総数） | 人口（男） | 人口（女） | 
| --- | ------------ | ---------- | ---------- | 
| 628 | 832832       | 407910     | 424922     | 
| 932 | 832832       | 393073     | 439759     | 

```Python
_df[_df['人口（総数）']==832832]
```

|     | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| --- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 628 | 19             | 山梨県     | 昭和 | 60         | 1985       | 832832       | 407910     | 424922     | 
| 629 | 19             | 山梨県     | 昭和 | 60         | 1985       | 832832       | 393073     | 439759     | 
| 630 | 41             | 佐賀県     | 平成 | 27         | 2015       | 832832       | 407910     | 424922     | 
| 631 | 41             | 佐賀県     | 平成 | 27         | 2015       | 832832       | 393073     | 439759     | 


## 【DataFrameを結合する | join()】

- `DataFrame.join()`はpandas.DataFrameのメソッドのみとなります。
- インデックスをキーに結合します。

```Python
df_1 = df[['都道府県コード', '都道府県名', '元号', '和暦（年）','西暦（年）']]
df_1.head()
```

|     | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 
| --- | -------------- | ---------- | ---- | ---------- | ---------- | 
| 0   | 1              | 北海道     | 大正 | 9          | 1920       | 
| 1   | 2              | 青森県     | 大正 | 9          | 1920       | 
| 2   | 3              | 岩手県     | 大正 | 9          | 1920       | 
| 3   | 4              | 宮城県     | 大正 | 9          | 1920       | 
| 4   | 5              | 秋田県     | 大正 | 9          | 1920       | 


```Python
df_2 = df[['人口（総数）', '人口（男）', '人口（女）']]
df_2.head()
```

|     | 人口（総数） | 人口（男） | 人口（女） | 
| --- | ------------ | ---------- | ---------- | 
| 0   | 2359183      | 1244322    | 1114861    | 
| 1   | 756454       | 381293     | 375161     | 
| 2   | 845540       | 421069     | 424471     | 
| 3   | 961768       | 485309     | 476459     | 
| 4   | 898537       | 453682     | 444855     | 

```Python
df_1.join(df_2)
# pd.concat([df_1, df_2], axis=1)と同じ
```

|                      | 都道府県コード | 都道府県名 | 元号 | 和暦（年） | 西暦（年） | 人口（総数） | 人口（男） | 人口（女） | 
| -------------------- | -------------- | ---------- | ---- | ---------- | ---------- | ------------ | ---------- | ---------- | 
| 0                    | 1              | 北海道     | 大正 | 9          | 1920       | 2359183      | 1244322    | 1114861    | 
| 1                    | 2              | 青森県     | 大正 | 9          | 1920       | 756454       | 381293     | 375161     | 
| 2                    | 3              | 岩手県     | 大正 | 9          | 1920       | 845540       | 421069     | 424471     | 
| 3                    | 4              | 宮城県     | 大正 | 9          | 1920       | 961768       | 485309     | 476459     | 
| 4                    | 5              | 秋田県     | 大正 | 9          | 1920       | 898537       | 453682     | 444855     | 
| ...                  | ...            | ...        | ...  | ...        | ...        | ...          | ...        | ...        | 
| 934                  | 43             | 熊本県     | 平成 | 27         | 2015       | 1786170      | 841046     | 945124     | 
| 935                  | 44             | 大分県     | 平成 | 27         | 2015       | 1166338      | 551932     | 614406     | 
| 936                  | 45             | 宮崎県     | 平成 | 27         | 2015       | 1104069      | 519242     | 584827     | 
| 937                  | 46             | 鹿児島県   | 平成 | 27         | 2015       | 1648177      | 773061     | 875116     | 
| 938                  | 47             | 沖縄県     | 平成 | 27         | 2015       | 1433566      | 704619     | 728947     | 
| 939 rows × 8 columns |                |            |      |            |            |              |            |            | 


**ポイント**

- 同じ行数のDataFrame同士を結合する場合、重複する列を片方のデータから削除してから`concat()`関数もしくは`DataFrame.join()`で結合する方が良いと思います。
- DataFrameとSeriesを結合する場合は、`concat()`関数のみ使用できます。


## 【おわりに】

今回はその中でも「concat」、「merge」、「join」について、それぞれの違いに触れながら紹介しました。

データ形式や使用用途に応じて結合方法を選ぶ必要がありますが、個人的には`pd.concat()`関数が万能なのではないかと思います。

今回、使用したCSVファイルやJupyter NotebookはGitHubに公開しています。
Jupyter Notebookは下記コマンドでダウンロードできるので、自由に使って是非練習してみてください。

```Shell
$ curl https://raw.githubusercontent.com/nakachan-ing/python-references/master/Pandas/pandasでDataFrameを結合する.ipynb -O
```

https://github.com/nakachan-ing/python-references/tree/master/Pandas