pandasで外部ファイルを読み込むときのdtype=strに気を付けろ

> 2019/04/05更新
> 現在のバージョン(0.24.1)ではxlsxの挙動がcsvと同じになっていました。
> JSONは相変わらずです。
> また気づき次第更新します。

to 昨日の私

何かしらのデータをDataFrameに変換する際、"001"の頭の00が取れるなど意図しない挙動を避けるためにいったん全部文字列型で受け取ろうという設定が`dtype=str`です。
これに於けるnullの扱いがcsv、xlsx、jsonでそれぞれ違ったのでメモ。

# 用意したデータ
```csv:test.csv
name,code
すし,001
ピザ,002
カレー,
```
```json:test.json
[
    {"name":"すし", "code":"001"},
    {"name":"ピザ", "code":"002"},
    {"name":"カレー", "code":null}
]
```
xlsxはcsvと同じなので省略

# 読み込み
```python
import pandas
import pathlib
import IPython.display

csv_path = pathlib.Path('./test.csv')
csv = pandas.read_csv(csv_path, dtype=str, encoding='utf8')
display(csv)
```
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>name</th>
      <th>code</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>すし</td>
      <td>001</td>
    </tr>
    <tr>
      <th>1</th>
      <td>ピザ</td>
      <td>002</td>
    </tr>
    <tr>
      <th>2</th>
      <td>カレー</td>
      <td>NaN</td>
    </tr>
  </tbody>
</table>
```python
xlsx_path = pathlib.Path('./test.xlsx')
xlsx = pandas.read_excel(xlsx_path, dtype=str, encoding='utf8')
display(xlsx)
```
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>name</th>
      <th>code</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>すし</td>
      <td>001</td>
    </tr>
    <tr>
      <th>1</th>
      <td>ピザ</td>
      <td>002</td>
    </tr>
    <tr>
      <th>2</th>
      <td>カレー</td>
      <td>nan</td>
    </tr>
  </tbody>
</table>
```python
json_path = pathlib.Path('./test.json')
json = pandas.read_json(json_path, dtype=str, encoding='utf8')
display(json)
```
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>code</th>
      <th>name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>001</td>
      <td>すし</td>
    </tr>
    <tr>
      <th>1</th>
      <td>002</td>
      <td>ピザ</td>
    </tr>
    <tr>
      <th>2</th>
      <td>None</td>
      <td>カレー</td>
    </tr>
  </tbody>
</table>

見事にバラけました。

# fillna()
それぞれのDataFrameにnullを一括置換する`fillna()`をあててみます。

```python
csv.fillna("000", inplace=True)
display(csv)
```
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>name</th>
      <th>code</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>すし</td>
      <td>001</td>
    </tr>
    <tr>
      <th>1</th>
      <td>ピザ</td>
      <td>002</td>
    </tr>
    <tr>
      <th>2</th>
      <td>カレー</td>
      <td>000</td>
    </tr>
  </tbody>
</table>
csvはうまくいきましたが…

```python
xlsx.fillna("000", inplace=True)
display(xlsx)
```
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>name</th>
      <th>code</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>すし</td>
      <td>001</td>
    </tr>
    <tr>
      <th>1</th>
      <td>ピザ</td>
      <td>002</td>
    </tr>
    <tr>
      <th>2</th>
      <td>カレー</td>
      <td>nan</td>
    </tr>
  </tbody>
</table>

```python
json.fillna("000", inplace=True)
display(json)
```
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>code</th>
      <th>name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>001</td>
      <td>すし</td>
    </tr>
    <tr>
      <th>1</th>
      <td>002</td>
      <td>ピザ</td>
    </tr>
    <tr>
      <th>2</th>
      <td>None</td>
      <td>カレー</td>
    </tr>
  </tbody>
</table>

xlsxとjsonでは失敗します。

#原因
"nan"、"None"という文字列に変換されるためです。
`replace()`しましょう。