[Python / Pandas] DataFrameに対して`replace`で`None`に置き換えようとするとバグが発生する
何が起きたか
pandas
のDataFrame
にあるreplace
メソッドを使い、np.nan
をNone
に置換しようとしたらバグが発生した(ように見えた)
Environment
Google Colaboratory で実施
ソースコード
1. 置換前のDataFrame作成
動作確認用のDataFrameがこちら
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方法その1
バグが起こる方
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方法その2
大丈夫?な方
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のままでした
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'):
日本語で書かれてたらもう少し早く気づけたかも...
その他関連資料
- nan_to_num
最新のnumpyにはnan_to_num
というメソッドがあり、こちらでnp.nan
を他の値に置き換えられるらしい
もしかしたら、これなら今回のようなバグは起きないかも(試せていない)
https://numpy.org/doc/stable/reference/generated/numpy.nan_to_num.html
- 逆の操作をしようとした場合
ちょっと関係あるのかわからないけれど、
None
をnp.nan
で埋めようとする場合も、別の問題が発生する模様
最新のnumpyには
nan_to_num
というメソッドがあり、こちらでnp.nan
を他の値に置き換えられるらしいもしかしたら、これなら今回のようなバグは起きないかも(試せていない) https://numpy.org/doc/stable/reference/generated/numpy.nan_to_num.html
None
をnp.nan
で埋めようとする場合も、別の問題が発生する模様Author And Source
この問題について([Python / Pandas] DataFrameに対して`replace`で`None`に置き換えようとするとバグが発生する), 我々は、より多くの情報をここで見つけました https://qiita.com/siruku6/items/79e4ee6925ea146bb0a0著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .