複数のDataFrameの結合(merge, concat)

##はじめに

私のインターン先であるレッドフォックス株式会社では
cyzen([https://www.cyzen.cloud/](https://www.cyzen.cloud/))
という営業支援システムアプリを開発しています。

今回、このアプリの顧客のデータを、Pythonを用いて分析する
にあたって、PandasのDataFrame上での様々な処理を行う必要が
あったため、ここにまとめます。

###作業内容
- DataFrameのmergeメソッド、concatメソッドの利用

###データの内容
顧客となる企業は、2週間程度の試用期間の中でその機能を体験し、
その後実際に導入するかどうかを判断します。

分析に用いたデータは、この試用期間中の顧客の、企業IDとアプリの
各機能の利用履歴です。

なお、上記のデータは、個人が特定できないようマスクされ、
利用日時のみの情報となっています。また、過去データの一部
をサンプルとして抽出したものを利用しています。


##DataFrameのmergeメソッドによる結合
複数のDataFrameを共通の列を基準に結合するメソッドです。

1\. pandasライブラリのインポート、ファイルの読み込みをする。

```python:
#ライブラリのインポート
import pandas as pd

#DataFrameを読み込み。今回はtsvファイルを読み込みました。
df_1 = pd.read_csv('/Users/data/trial.tsv', sep='\t')
df_2 = pd.read_csv('/Users/data/history.tsv', sep='\t')

```

``df_1``、``df_2``は以下のようになっています。
``df_1``

|Index|company_id|limit_count|production|
|----:|---------:|----------:|---------:|
|0    |      1010|          3|         1|
|1    |      1020|         10|         0|
|2|1030|10|0|
|     |          |           |          |
|n    |      2000|         30|         1|

``df_2``

|Index|company_id|updated_at|
|----:|---------:|---------:|
|    0|      1010|2017-01-01 00:00:00|
|1    |1010|2017-01-01 00:00:05|
|2|1010|2017-01-01 00:00:10|
|3|1020|2017-01-01 00:01:00
|||||
|m|2000|2017-12-31 00:00:00|

2\. ``df_1``、``df_2``をmergeメソッドを使い結合する。
``pd.merge(df_1, df_2, on='基準とする列名')``を用います。列'cid'を基準に結合します。
共通する列が1つであれば、引数に``on``を入れる必要はありません。

```python:
df_3 = pd.merge(df_1, df_2, on='cid')
#今回は'cid'以外にも共通する列'Index'があるため、onを指定しています。
```
``df_3``は以下のようになります。

|cid|Index_x|  limit_count | production  |    Index_y|     updated_at | 
|--:|--:|--:|--:|--:|--:|
|1010| 0 |         3 |          1 |       0 |2017-01-01 00:00:00 |       0|
|1010| 0  |        3 |          1 |      1 |2017-01-01 00:00:05 |      1|
|1010|  0  |        3 |          1  |      2 |2017-01-01 00:00:10  |      2|
|1020|1 |        10 |        0   |     3|2017-01-01 00:01:00   |     3|
|1030|2 |        10  |         0   |     4| 2017-01-01 00:02:00    |    4|
|||||||
|2000|n |        30  |         1   |     m| 2017-12-31 00:00:00  |      5|

基準となった列'cid'が左端となり、両者が左右方向に結合されました。
さらに、'cid'1010の行数は行数の多い方に統一されています。

また、両者の列'Index'はそれぞれ'Index_x', 'Index_y'という名前に
自動的に変更されています。
これらの列は不要なため以下の操作で取り除きます。

```python:
df_3 = df_3.loc[:,['cid', 'limit_cnt', 'updated_at', 'production']]
# locで指定した順番にDataFrameの各列を並べ替えることができます。
```

``df_3``は以下のようになります。

|cid|limit_count|updated_at|production|
|--:|--:|--:|--:|
|1010|3|2017-01-01 00:00:00|1|
|1010|3|2017-01-01 00:00:05|1|
|1010|3|2017-01-01 00:00:05|1|
|1020|10|2017-01-01 00:01:00|0|
||||
|2000|30|2017-12-31 00:00:00|1|

###引数``on``の値を与えない場合
共通する列が複数あるときに``on``の値を与えない場合、共通の列全てを
基準としてDataFrameを結合してしまいます。上記の例で同様にすると、

```python:
df_3 = pd.merge(df_1, df_2)
```

``df_3``は以下のように、共通する列'cid'、'Index'の両者の値が同じになっている1行
のみになってしまいました。

| cid  |limit_cnt | production|  Index| updated_at|
|--:|--:|--:|--:|--:|
|0 | 1010 |         3 |          1 |     0| 2017-01-01|



##DataFrameのconcatメソッドによる結合
mergeメソッドでは共通の列を基準に複数のDataFrameを結合しましたが、
concatメソッドでは単純に複数のDataFrameを列方向あるいは行方向に結合します。

両者のサンプル数あるいは列が同一である場合に用います。
ここでは、scikit-learnに収録されている回帰分析用のBoston市郊外の住宅価格データセット
をDataFrameとして結合させたいと思います。

1\. ライブラリのインポート、データセットの読み込みをする。

```python:
import pandas as pd

from sklearn.datasets import load_boston # bostonデータを格納したクラス
boston = load_boston()        # インスタンスの生成

# データの説明変数となる部分をdf_dataとします。
df_data = pd.DataFrame(boston.data, columns=boston.feature_names)
df_data.head() # DataFrame名.head()でDataFrameの最初の5行を表示できます。

# 目的変数となる部分をdf_targetとします。
df_target = pd.DataFrame(boston.target, columns=['MEDV'])
```
``df_data``, ``df_target``はそれぞれ以下のようになっています。

``df_data``

||CRIM|ZN|INDUS|CHAS|NOX|RM| AGE|DIS|RAD|TAX|
|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
|0|0.00632|18.0| 2.31| 0.0|0.538|6.575|65.2|4.0900|1.0|296.0|
|1|0.02731| 0.0| 7.07| 0.0|0.469|6.421|78.9|4.9671|2.0|242.0|
|2|0.02729| 0.0| 7.07| 0.0|0.469|7.185|61.1|4.9671|2.0|242.0|
|3|0.03237| 0.0| 2.18| 0.0|0.458|6.998|45.8|6.0622|3.0|222.0| 
|4|0.06905| 0.0| 2.18| 0.0|0.458|7.147|54.2|6.0622|3.0|222.0|

``df_target``

||MEDV|
|--:|--:|
|0|24.0|
|1|21.6|
|2|34.7|
|3|33.4|
|4|36.2|

2\. concatメソッドを使い両者を結合する。

```python:
df_1 = pd.concat([df_data, df_target], axis=1) 
# 引数axisの値を0か1にすることによって縦（列方向）、横（行方向）のどちらに結合するかを指定できます。
# 今回は横方向に結合するためaxis=1としています。
```



``df_1``は以下のようになります。

||CRIM|ZN|INDUS|CHAS|NOX|RM| AGE|DIS|RAD|TAX|MEDV|
|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|---:|
|0|0.00632|18.0| 2.31| 0.0|0.538|6.575|65.2|4.0900|1.0|296.0|24.0|
|1|0.02731| 0.0| 7.07| 0.0|0.469|6.421|78.9|4.9671|2.0|242.0|21.6|
|2|0.02729| 0.0| 7.07| 0.0|0.469|7.185|61.1|4.9671|2.0|242.0|34.7|
|3|0.03237| 0.0| 2.18| 0.0|0.458|6.998|45.8|6.0622|3.0|222.0|33.4|
|4|0.06905| 0.0| 2.18| 0.0|0.458|7.147|54.2|6.0622|3.0|222.0|36.2|