Python DataFrameを縦方向に結合

### DataFrameを縦方向に結合

日々のデータを一定期間ごとにcsvで取得し、結合する場合を想定しています。
`csv`ファイルを`DataFrame.read_csv`で取得し結合するときとかに使えると思います。

`csv`ファイルを`DataFrame.read_csv`で取得した結果がdf1、df2、df3を想定しています。 
(df3はタイトル行に項目が増えている状態です)


```python
import pandas as pd
df1 = pd.DataFrame([['2022/1/4', '500', '400', '40'],
                    ['2022/1/5', '1000', '800', '80'],
                    ['2022/1/6', '3000', '2400', '240']],
                   columns=['date', 'value', 'cost', 'tax'])
df1['date'] = pd.to_datetime(df1['date']).dt.date
df2 = pd.DataFrame([['2022/1/6', '3000', '2400', '240'],
                    ['2022/1/7', '1000', '800', '80'],
                    ['2022/1/8', '3000', '2400', '240'],
                    ['2022/1/9', '1500', '1200', '120']],
                   columns=['date', 'value', 'cost', 'tax'])
df2['date'] = pd.to_datetime(df2['date']).dt.date
df3 = pd.DataFrame([['2022/1/9', '1500', '1200', '120', 'NaN'],
                    ['2022/1/10', '500', '400', '40', '5'],
                    ['2022/1/11', '1000', '800', '80', '10']],
                   columns=['date', 'value', 'cost', 'tax', 'tax2'])
df3['date'] = pd.to_datetime(df3['date']).dt.date
```

df1、df2、df3を`concat`で結合します。`concat`だと、columnsが同じの場合はそのまま結合されます。
( `ignore_index=True`を入れることでインデックスをつけなおします。 )


```python
df = pd.concat([df1, df2, df3], ignore_index=True)
df
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>date</th>
      <th>value</th>
      <th>cost</th>
      <th>tax</th>
      <th>tax2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2022-01-04</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2022-01-05</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2022-01-06</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2022-01-06</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2022-01-07</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2022-01-08</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>6</th>
      <td>2022-01-09</td>
      <td>1500</td>
      <td>1200</td>
      <td>120</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>7</th>
      <td>2022-01-09</td>
      <td>1500</td>
      <td>1200</td>
      <td>120</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>8</th>
      <td>2022-01-10</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>5</td>
    </tr>
    <tr>
      <th>9</th>
      <td>2022-01-11</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>10</td>
    </tr>
  </tbody>
</table>
</div>



`append`でも同じことができます。複数を同時に結合する場合は`cancat`のほうが良いかもしれませんが、`for`文などを使って結合する場合は`append`が良いと思います。
( `ignore_index=True`を入れることでインデックスをつけなおします。 )


```python
df = pd.DataFrame()
for d in [df1, df2, df3]:
    df = df.append(d, ignore_index=True)
df
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>date</th>
      <th>value</th>
      <th>cost</th>
      <th>tax</th>
      <th>tax2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2022-01-04</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2022-01-05</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2022-01-06</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2022-01-06</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2022-01-07</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2022-01-08</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>6</th>
      <td>2022-01-09</td>
      <td>1500</td>
      <td>1200</td>
      <td>120</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>7</th>
      <td>2022-01-09</td>
      <td>1500</td>
      <td>1200</td>
      <td>120</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>8</th>
      <td>2022-01-10</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>5</td>
    </tr>
    <tr>
      <th>9</th>
      <td>2022-01-11</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>10</td>
    </tr>
  </tbody>
</table>
</div>



`merge`でもkeyがわかっていれば使えますが、変わる場合は決めたエラーとなる場合があるので、注意が必要です。
df1、df2はcolumnsが一致しているが、df3は異なる。df3のcolumnsをkeyにすると'tax2'がdf1、df2に含まれていないため、エラーとなる。
`mearge`の場合は外部結合`how=outer`を設定する。重複行の削除も一度にできるメリットはあります。


```python
key = list(df1.keys())
df = pd.DataFrame([], columns=key)
for d in [df1, df2, df3]:
    df = df.merge(d, on=key, how='outer')
df
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>date</th>
      <th>value</th>
      <th>cost</th>
      <th>tax</th>
      <th>tax2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2022-01-04</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2022-01-05</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2022-01-06</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2022-01-07</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2022-01-08</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2022-01-09</td>
      <td>1500</td>
      <td>1200</td>
      <td>120</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>6</th>
      <td>2022-01-10</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>5</td>
    </tr>
    <tr>
      <th>7</th>
      <td>2022-01-11</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>10</td>
    </tr>
  </tbody>
</table>
</div>



`concat`、`append`で結合した場合は、`drop_duplicates`で重複の削除ができる


```python
df = pd.concat([df1, df2, df3], ignore_index=True)
df.drop_duplicates(subset='date', keep='last')
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>date</th>
      <th>value</th>
      <th>cost</th>
      <th>tax</th>
      <th>tax2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2022-01-04</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2022-01-05</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2022-01-06</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2022-01-07</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2022-01-08</td>
      <td>3000</td>
      <td>2400</td>
      <td>240</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>7</th>
      <td>2022-01-09</td>
      <td>1500</td>
      <td>1200</td>
      <td>120</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>8</th>
      <td>2022-01-10</td>
      <td>500</td>
      <td>400</td>
      <td>40</td>
      <td>5</td>
    </tr>
    <tr>
      <th>9</th>
      <td>2022-01-11</td>
      <td>1000</td>
      <td>800</td>
      <td>80</td>
      <td>10</td>
    </tr>
  </tbody>
</table>
</div>