環境
- Python 3.12.1
- panda 2.2.2
はじめに
pandas.Sereis.mapを使ったら、pandas.NAがnumpy.nanに変換されるときがありました。
実際に試して、どう変換されるかを確認しました。
結果
pd.NAを含む場合
dtypeがInt64
In [51]: s2 = pd.Series([1, pd.NA],dtype="Int64")
In [52]: s2
Out[52]:
0 1
1 <NA>
dtype: Int64
In [53]: s2.map(lambda e: e)
Out[53]:
0 1.0
1 NaN
dtype: float64
pd.NAがnp.nanに変わりました。またdtypeがInt64からfloat64に変わりました。int64でなくfloat64に変わったのは、np.nanの型がfloatだからでしょう。
dtypeがstring
In [54]: s3 = pd.Series(["a",pd.NA],dtype="string")
In [55]: s3
Out[55]:
0 a
1 <NA>
dtype: string
In [56]: s3.map(lambda e: e)
Out[56]:
0 a
1 <NA>
dtype: object
pd.NAはそのままの値でした。しかし、dtypeがstringからobjectに変わりました。
pd.NAを含まない場合
dtypeがInt64
In [60]: s4 = pd.Series([1,2],dtype="Int64")
In [62]: s4
Out[62]:
0 1
1 2
dtype: Int64
In [61]: s4.map(lambda e: e)
Out[61]:
0 1
1 2
dtype: int64
dtypeがInt64からint64に変わりました。
dtypeがstring
In [64]: s5 = pd.Series(["a","b"],dtype="string")
In [65]: s5
Out[65]:
0 a
1 b
dtype: string
In [66]: s5.map(lambda e: e)
Out[66]:
0 a
1 b
dtype: object
dtypeがstringからobjectに変わりました。
分かったこと
Series.mapに挙動について分かったことです。
- pandas独自のdtypeがnumpy用のdtypeに変換されます。たとえば
Int64がint64に、stringがobjectに変換されます。 - dtypeが
float64やint64の列はpd.NAを含められないので、pd.NAはnp.nanに変換されます。ただしnp.nanはfloat型なので、pd.NAを含むdtypeがInt64の列はfloat64に変換されます。 - dtypeが
objectの列はpd.NAを含むことができるので、dtypeがstringの列に含まれるpd.NAはnp.nanに変換されません。
補足
pandas 2.1とpandas2.2で挙動が異なるようです。今後のpandasバージョンアップで、挙動が変わるかもしれません。