[Python / Pandas] DataFrameに対して`replace`で`None`に置き換えようとするとバグが発生する

# 何が起きたか

`pandas`の`DataFrame`にある`replace`メソッドを使い、`np.nan`を`None`に置換しようとしたらバグが発生した（ように見えた）

# Environment

Google Colaboratory で実施

# ソースコード

## 1. 置換前のDataFrame作成
動作確認用のDataFrameがこちら

```python
import pandas as pd
import numpy as np

indexes = [
    datetime.datetime(2020, 1, 1, 11, 50),
    datetime.datetime(2020, 1, 1, 12, 50),
    datetime.datetime(2020, 1, 1, 12, 52),
    datetime.datetime(2020, 1, 1, 18, 50),
    datetime.datetime(2020, 1, 1, 19, 50),
    datetime.datetime(2020, 1, 1, 21, 50),
]
df = pd.DataFrame({
    'high': [1, np.nan, 3, np.nan, np.nan, 11],
    'close': [4, 5, 6, 7, np.nan, 2],
    'memo': ['sign', '', np.nan, 'sign2', np.nan, 'sign3'],
    'bool': [True, None, True, False, None, False],
    'stoploss': [True, None, True, False, None, False]
}, index=indexes)

df
->                    high   close   memo   bool	stoploss
2020-01-01 11:50:00   1.0    4.0     sign   True	True
2020-01-01 12:50:00   NaN    5.0            None	None
2020-01-01 12:52:00   3.0    6.0     NaN    True	True
2020-01-01 18:50:00   NaN    7.0     sign2  False	False
2020-01-01 19:50:00   NaN    NaN     NaN    None	None
2020-01-01 21:50:00   11.0   2.0     sign3  False	False
```

## 2. replace方法その１

バグが起こる方

```python
df.replace(np.nan, None)
->                   high	close	memo	bool	stoploss
2020-01-01 11:50:00  1.0	4.0     sign	True	True
2020-01-01 12:50:00  1.0	5.0             True    True
2020-01-01 12:52:00  3.0	6.0             True	True
2020-01-01 18:50:00  3.0	7.0     sign2   False	False
2020-01-01 19:50:00  3.0	7.0     sign2   False   False
2020-01-01 21:50:00  11.0	2.0     sign3	False	False
```

...なんじゃこりゃ！！ヾﾉ｡ÒдÓ)ﾉｼ ﾊﾞﾝﾊﾞﾝ!!
`np.nan`だったところが`None`じゃなくて、直前の値で埋められてます
（`fillna`されたみたいになってます）

## 3. replace方法その２

大丈夫？な方

```python
df.replace({np.nan: None})
->                    high   close   memo   bool	stoploss
2020-01-01 11:50:00   1      4       sign   True	True
2020-01-01 12:50:00   None   5	            None	None
2020-01-01 12:52:00   3      6       None   True	True
2020-01-01 18:50:00   None   7       sign2  False	False
2020-01-01 19:50:00   None   None    None   None	None
2020-01-01 21:50:00   11     2       sign3  False	False
```

期待通りではある（？
いや、気づいたけど、なんか、`float`が、全部整数にされてる....
だいじょばないです（助けて）

...なんて一瞬（30分以上）焦りましたが、よく見てみたら中身はfloatのままでした

```python
tmp_df = df.replace({np.nan: None})

tmp_df.values
-> array([[1.0, 4.0, 'sign', True, True],
       [None, 5.0, '', None, None],
       [3.0, 6.0, None, True, True],
       [None, 7.0, 'sign2', False, False],
       [None, None, None, None, None],
       [11.0, 2.0, 'sign3', False, False]], dtype=object)
```
ε-(´∀｀*)ﾎｯ

この書き方覚えとかないとね...( ..)φ`df.replace({np.nan: None})`


# 参考資料

一応、pandasの公式ドキュメントでもこの件は言及されています。
ただ、見つけるのにかなり時間がかかったので、今回記録しておくことにしました。

> When value=None and to_replace is a scalar, list or tuple, replace uses the method parameter (default ‘pad’) to do the replacement. So this is why the ‘a’ values are being replaced by 10 in rows 1 and 2 and ‘b’ in row 4 in this case. The command s.replace('a', None) is actually equivalent to s.replace(to_replace='a', value=None, method='pad'):

- [pandas.DataFrame.replace](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) より抜粋

日本語で書かれてたらもう少し早く気づけたかも...

# その他関連資料

- nan_to_num  
最新のnumpyには`nan_to_num`というメソッドがあり、こちらで`np.nan`を他の値に置き換えられるらしい  
もしかしたら、これなら今回のようなバグは起きないかも（試せていない）
https://numpy.org/doc/stable/reference/generated/numpy.nan_to_num.html
- 逆の操作をしようとした場合
ちょっと関係あるのかわからないけれど、`None`を`np.nan`で埋めようとする場合も、別の問題が発生する模様

[StackOverflow : Replace None with NaN in pandas dataframe](https://stackoverflow.com/questions/23743460/replace-none-with-nan-in-pandas-dataframe)