pandas のデータフレームをエクセルに書き出す


pandas の `to_excel` を使って、データフレームをエクセルに書き出します。

* [pandas.DataFrame.to_excel — pandas 0.15.1
documentation](http://pandas.pydata.org/pandas-
docs/version/0.15.1/generated/pandas.DataFrame.to_excel.html)

まずは、必要な Python モジュールがインポートできることを確認します。

```python
import pandas as pd
import matplotlib.pyplot as plt
from pandas.io import wb
import xlsxwriter
```

# データの読み込み

世界銀行の API を使って、アメリカと日本の人口とGDPを取得します。indicator 文字列は世界銀行の API から取得します。

```python
df_gdp = wb.download(indicator='NY.GDP.PCAP.KD', country=['US', 'JP'], start=1960, end=2013)
df_population = wb.download(indicator='SP.POP.TOTL', country=['US', 'JP'], start=1960, end=2013)
```

## データの確認

```python
df_gdp.head(3)
```

<div style="max-height:1000px;max-width:1500px;overflow:auto;">
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th></th>
      <th>NY.GDP.PCAP.KD</th>
    </tr>
    <tr>
      <th>country</th>
      <th>year</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th rowspan="3" valign="top">Japan</th>
      <th>2013</th>
      <td> 37432.840747</td>
    </tr>
    <tr>
      <th>2012</th>
      <td> 36800.922307</td>
    </tr>
    <tr>
      <th>2011</th>
      <td> 36203.430066</td>
    </tr>
  </tbody>
</table>
</div>


```python
df_gdp.dtypes
```

    NY.GDP.PCAP.KD    float64
    dtype: object
    df_gdp.index

    MultiIndex(levels=[['Japan', 'United States'], ['1960', '1961', '1962', '1963', '1964', '1965', '1966', '1967', '1968', '1969', '1970', '1971', '1972', '1973', '1974', '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982', '1983', '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992', '1993', '1994', '1995', '1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013']],
               labels=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...], [53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, ...]],
               names=['country', 'year'])

```python
df_gdp.describe()
```

<div style="max-height:1000px;max-width:1500px;overflow:auto;">
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>NY.GDP.PCAP.KD</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>count</th>
      <td>   108.000000</td>
    </tr>
    <tr>
      <th>mean</th>
      <td> 28015.188967</td>
    </tr>
    <tr>
      <th>std</th>
      <td> 10061.123534</td>
    </tr>
    <tr>
      <th>min</th>
      <td>  7079.439251</td>
    </tr>
    <tr>
      <th>25%</th>
      <td> 20152.131354</td>
    </tr>
    <tr>
      <th>50%</th>
      <td> 28858.039661</td>
    </tr>
    <tr>
      <th>75%</th>
      <td> 35165.327764</td>
    </tr>
    <tr>
      <th>max</th>
      <td> 45863.019564</td>
    </tr>
  </tbody>
</table>
</div>

GDP のデータフレームは：

* "country" と "year" のマルチインデックスになっている
* 108個の要素がある
* 最小値は 7079.439251、最大値は 45863.019564 になっている
* データは最新のものから降順になっている

人口のデータフレームも同じような構成になっています。

## データを整形

このままでは使いにくいのでデータを整形します。

```python
df_gdp.unstack(level=0).head(3)
```

<div style="max-height:1000px;max-width:1500px;overflow:auto;">
<table border="1" class="dataframe">
  <thead>
    <tr>
      <th></th>
      <th colspan="2" halign="left">NY.GDP.PCAP.KD</th>
    </tr>
    <tr>
      <th>country</th>
      <th>Japan</th>
      <th>United States</th>
    </tr>
    <tr>
      <th>year</th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1960</th>
      <td> 7079.439251</td>
      <td> 15469.072967</td>
    </tr>
    <tr>
      <th>1961</th>
      <td> 7728.000388</td>
      <td> 15564.690585</td>
    </tr>
    <tr>
      <th>1962</th>
      <td> 8338.409056</td>
      <td> 16262.092906</td>
    </tr>
  </tbody>
</table>
</div>


```python
df_gdp.unstack(level=0).describe()
```

<div style="max-height:1000px;max-width:1500px;overflow:auto;">
<table border="1" class="dataframe">
  <thead>
    <tr>
      <th></th>
      <th colspan="2" halign="left">NY.GDP.PCAP.KD</th>
    </tr>
    <tr>
      <th></th>
      <th>Japan</th>
      <th>United States</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>count</th>
      <td>    54.000000</td>
      <td>    54.000000</td>
    </tr>
    <tr>
      <th>mean</th>
      <td> 25134.970999</td>
      <td> 30895.406935</td>
    </tr>
    <tr>
      <th>std</th>
      <td>  9716.583553</td>
      <td>  9646.035006</td>
    </tr>
    <tr>
      <th>min</th>
      <td>  7079.439251</td>
      <td> 15469.072967</td>
    </tr>
    <tr>
      <th>25%</th>
      <td> 17457.921985</td>
      <td> 22981.450242</td>
    </tr>
    <tr>
      <th>50%</th>
      <td> 26005.632842</td>
      <td> 30462.082595</td>
    </tr>
    <tr>
      <th>75%</th>
      <td> 33991.192095</td>
      <td> 40658.654684</td>
    </tr>
    <tr>
      <th>max</th>
      <td> 37432.840747</td>
      <td> 45863.019564</td>
    </tr>
  </tbody>
</table>
</div>


```python
df_gdp.unstack(level=0).plot(figsize=(16, 4), colormap='seismic')
```

![worldbank_to_excel_16_1.png](https://qiita-image-store.s3.amazonaws.com/0/37996/0c24b38b-2fa5-43aa-3239-a73b336f7d39.png "worldbank_to_excel_16_1.png")

人口のデータも同様に変換します。

```python
df_population.unstack(level=0).head(3)
```

<div style="max-height:1000px;max-width:1500px;overflow:auto;">
<table border="1" class="dataframe">
  <thead>
    <tr>
      <th></th>
      <th colspan="2" halign="left">SP.POP.TOTL</th>
    </tr>
    <tr>
      <th>country</th>
      <th>Japan</th>
      <th>United States</th>
    </tr>
    <tr>
      <th>year</th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1960</th>
      <td> 92500572</td>
      <td> 180671000</td>
    </tr>
    <tr>
      <th>1961</th>
      <td> 94943000</td>
      <td> 183691000</td>
    </tr>
    <tr>
      <th>1962</th>
      <td> 95832000</td>
      <td> 186538000</td>
    </tr>
  </tbody>
</table>
</div>


```python
ax = df_population.unstack(level=0).plot(figsize=(16, 4), colormap='seismic')
```

![worldbank_to_excel_19_0.png](https://qiita-image-store.s3.amazonaws.com/0/37996/ea26bfa3-685e-00d8-e859-c60fdf9a3c0d.png "worldbank_to_excel_19_0.png")


５年の移動平均を計算してみると、アメリカは人口増加、日本は人口横ばいである傾向が少しハッキリします。

```python
ax = pd.stats.moments.rolling_mean(df_population.unstack(level=0), 5).plot(figsize=(16, 4), colormap='seismic')
```

![worldbank_to_excel_21_0.png](https://qiita-image-store.s3.amazonaws.com/0/37996/4235e9e1-3604-1496-f326-d8518fd9c7da.png "worldbank_to_excel_21_0.png")


```python
ax = pd.stats.moments.rolling_std(df_population.unstack(level=0)['SP.POP.TOTL'], 5).plot(figsize=(16, 4), colormap='seismic')
```

![worldbank_to_excel_22_0.png](https://qiita-image-store.s3.amazonaws.com/0/37996/0d24aae7-0f75-879e-de1c-3db1986ef605.png "worldbank_to_excel_22_0.png")


## データの結合

２つのデータフレームを結合します。

```python
pd.concat([df_gdp, df_population], axis=1).unstack(level=0).head(3)
```

<div style="max-height:1000px;max-width:1500px;overflow:auto;">
<table border="1" class="dataframe">
  <thead>
    <tr>
      <th></th>
      <th colspan="2" halign="left">NY.GDP.PCAP.KD</th>
      <th colspan="2" halign="left">SP.POP.TOTL</th>
    </tr>
    <tr>
      <th>country</th>
      <th>Japan</th>
      <th>United States</th>
      <th>Japan</th>
      <th>United States</th>
    </tr>
    <tr>
      <th>year</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1960</th>
      <td> 7079.439251</td>
      <td> 15469.072967</td>
      <td> 92500572</td>
      <td> 180671000</td>
    </tr>
    <tr>
      <th>1961</th>
      <td> 7728.000388</td>
      <td> 15564.690585</td>
      <td> 94943000</td>
      <td> 183691000</td>
    </tr>
    <tr>
      <th>1962</th>
      <td> 8338.409056</td>
      <td> 16262.092906</td>
      <td> 95832000</td>
      <td> 186538000</td>
    </tr>
  </tbody>
</table>
</div>


```python
df = pd.concat([df_gdp, df_population], axis=1).unstack(level=0)
df.describe()
```

<div style="max-height:1000px;max-width:1500px;overflow:auto;">
<table border="1" class="dataframe">
  <thead>
    <tr>
      <th></th>
      <th colspan="2" halign="left">NY.GDP.PCAP.KD</th>
      <th colspan="2" halign="left">SP.POP.TOTL</th>
    </tr>
    <tr>
      <th></th>
      <th>Japan</th>
      <th>United States</th>
      <th>Japan</th>
      <th>United States</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>count</th>
      <td>    54.000000</td>
      <td>    54.000000</td>
      <td> 5.400000e+01</td>
      <td> 5.400000e+01</td>
    </tr>
    <tr>
      <th>mean</th>
      <td> 25134.970999</td>
      <td> 30895.406935</td>
      <td> 1.171442e+08</td>
      <td> 2.460156e+08</td>
    </tr>
    <tr>
      <th>std</th>
      <td>  9716.583553</td>
      <td>  9646.035006</td>
      <td> 1.115320e+07</td>
      <td> 4.038823e+07</td>
    </tr>
    <tr>
      <th>min</th>
      <td>  7079.439251</td>
      <td> 15469.072967</td>
      <td> 9.250057e+07</td>
      <td> 1.806710e+08</td>
    </tr>
    <tr>
      <th>25%</th>
      <td> 17457.921985</td>
      <td> 22981.450242</td>
      <td> 1.085998e+08</td>
      <td> 2.123952e+08</td>
    </tr>
    <tr>
      <th>50%</th>
      <td> 26005.632842</td>
      <td> 30462.082595</td>
      <td> 1.217915e+08</td>
      <td> 2.412110e+08</td>
    </tr>
    <tr>
      <th>75%</th>
      <td> 33991.192095</td>
      <td> 40658.654684</td>
      <td> 1.268150e+08</td>
      <td> 2.813818e+08</td>
    </tr>
    <tr>
      <th>max</th>
      <td> 37432.840747</td>
      <td> 45863.019564</td>
      <td> 1.278173e+08</td>
      <td> 3.161288e+08</td>
    </tr>
  </tbody>
</table>
</div>

GDPを左軸、人口を右軸にしてグラフを描画してみます。

```python
ax = df.plot(figsize=(16, 6), colormap='seismic',
                 secondary_y=[('SP.POP.TOTL', 'Japan'), ('SP.POP.TOTL', 'United States')])
    ax.set_ylabel('GDP')
    _ = ax.right_ax.set_ylabel('Population')
```

![worldbank_to_excel_28_0.png](https://qiita-image-store.s3.amazonaws.com/0/37996/f694fa03-2fa2-525f-7ce0-6fcf3846e04b.png "worldbank_to_excel_28_0.png")

単一のデータフレームで扱えるようになりました。

５年単位での分散を計算すると、日本の人口は1980年ごろから伸び悩み、GDPは1995年ごろから横ばいと言えます。
アメリカの場合は、1990年ごろに人口増加の波があり、2000年ごろにGDPの増加がピークを迎え、定期的に波があると言えます。

```python
ax = pd.stats.moments.rolling_var(df, 5).plot(subplots=True, layout=(2, 2), figsize=(16, 6))
```

![worldbank_to_excel_31_0.png](https://qiita-image-store.s3.amazonaws.com/0/37996/c3e7206d-b9be-4322-e65e-3527941ed737.png "worldbank_to_excel_31_0.png")

## データの出力

エクセルに出力します。データフレームのメソッドを呼び出しますが、`xlsxwriter`
などのエクセル書き出しモジュールがインストールされている必要があります。

```python
df.to_excel('/data/sample.xlsx', sheet_name='Japan_US')
%ls /data
```

    sample.xlsx

出来上がったデータをエクセルで開いてみてください。LibreOffice などでも構いません。

複数のデータフレームを個別のシートに書き出す場合は、引数にファイル名ではなくライターオブジェクト (`ExcelWriter `)
を指定します。公式ドキュメントに例がありますが、詳しくは Stack Overflow などで探しましょう。

* [pandas.DataFrame.to_excel — pandas 0.15.1
documentation](http://pandas.pydata.org/pandas-
docs/stable/generated/pandas.DataFrame.to_excel.html)
* [creating multiple excel worksheets using data in a pandas dataframe - Stack
Overflow](http://stackoverflow.com/questions/21981820/creating-multiple-excel-
worksheets-using-data-in-a-pandas-dataframe)

# 動作環境

*version_information* 拡張を有効にしてあります。このノートブックの動作環境は以下のものです。

    %version_information numpy, pandas, matplotlib, xlsxwriter

<table><tr><th>Software</th><th>Version</th></tr><tr><td>Python</td><td>3.4.2 64bit [GCC 4.9.1]</td></tr><tr><td>IPython</td><td>2.3.1</td></tr><tr><td>OS</td><td>Linux 3.13.0 24 generic x86_64 with debian 8.0</td></tr><tr><td>numpy</td><td>1.9.1</td></tr><tr><td>pandas</td><td>0.15.1</td></tr><tr><td>matplotlib</td><td>1.4.2</td></tr><tr><td>xlsxwriter</td><td>0.6.4</td></tr><tr><td colspan='2'>Mon Dec 08 15:50:50 2014 UTC</td></tr></table>

※ このドキュメントは IPython Notebook を Markdown に変換して微調整したものです。

```bash
$ ipython nbconvert --to markdown /data/worldbank_to_excel.ipynb
```