環境
- Python 3.12.4
- pandas 2.2.3
- numpy 1.26.4
概要
pandas.Series
にnp.nan
かNone
どちらを設定すればよいのか、悩むときがありました。
そこで、pandas.Series
にNone
を格納しようとしたときに、どのような挙動になるかを確認しました。
結果
pandas.Series
オブジェクトの生成
None
のみを格納
In [67]: pd.Series([None])
Out[67]:
0 None
dtype: object
数値とNone
を格納
In [69]: pd.Series([None, 1])
Out[69]:
0 NaN
1 1.0
dtype: float64
None以外の値からdtypeがint64
に推測されます。Noneは、int64
型の欠損値としてnp.nan
に変換されます。しかし、np.nan
はfloat
なので、dtypeはint64
ではなくfloat64
になりました。
datetime型の値とNone
を格納
In [312]: import datetime
In [313]: pd.Series([None, datetime.datetime.now()])
Out[313]:
0 NaT
1 2024-11-20 10:12:45.863132
dtype: datetime64[ns]
dtypeがdatetime64
の場合、NoneはNaT
に変換されます。
None
とTrue
を格納する(dtypeを指定しない)
In [334]: pd.Series([None, True])
Out[334]:
0 None
1 True
dtype: object
In [335]: pd.Series([True])
Out[335]:
0 True
dtype: bool
dtypeがbool
の場合欠損値を格納できません。None
を格納するために、dtypeがobject
になったようです。
None
とTrue
を格納する(dtypeを指定する)
In [350]: pd.Series([None, True], dtype="bool")
Out[350]:
0 False
1 True
dtype: bool
dtypeがbool
の場合欠損値を格納できないので、None
はbool(None)
の結果False
に変換されました。
dtype="Int64"
を指定する
In [331]: pd.Series([None], dtype="Int64")
Out[331]:
0 <NA>
dtype: Int64
値の代入
dtypeがint64
のpandas.Series
にNone
を設定
In [121]: s = pd.Series([1])
In [122]: s
Out[122]:
0 1
dtype: int64
In [123]: s[0] = None
In [124]: s
Out[124]:
0 NaN
dtype: float64
dtypeがInt64
のpandas.Series
にNone
を設定
In [324]: s = pd.Series([1], dtype="Int64")
In [325]: s
Out[325]:
0 1
dtype: Int64
In [326]: s[0] = None
In [327]: s
Out[327]:
0 <NA>
dtype: Int64
dtypeがdatetime64
のpandas.Series
にNone
を設定
In [320]: s = pd.Series([datetime.datetime.now()])
In [321]: s
Out[321]:
0 2024-11-20 10:15:34.494504
dtype: datetime64[ns]
In [322]: s[0] = None
In [323]: s
Out[323]:
0 NaT
dtype: datetime64[ns]
dtypeがobject
のpandas.Series
にNone
を設定
In [125]: s2 = pd.Series(["foo"])
In [126]: s2
Out[126]:
0 foo
dtype: object
In [127]: s2[0] = None
In [128]: s2
Out[128]:
0 None
dtype: object
当然ではありますが、dtypeがobject
ならばNone
を格納できるので、None
は変換されません。
dtypeがbool
のpandas.Series
にNone
を設定
In [346]: s = pd.Series([True])
In [347]: s
Out[347]:
0 True
dtype: bool
In [348]: s[0] = None
<ipython-input-348-3e3b188ac867>:1: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value 'nan' has dtype incompatible with bool, please explicitly cast to a compatible dtype first.
s[0] = None
In [349]: s
Out[349]:
0 NaN
dtype: object
None
ではなくNaN
に変換されました。想定外の挙動でした。
なお、None
でなくpd.NA
を設定したときも同じ挙動でした。
In [352]: s = pd.Series([True])
In [353]: s[0] = pd.NA
<ipython-input-353-cfb9da72f810>:1: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value 'nan' has dtype incompatible with bool, please explicitly cast to a compatible dtype first.
s[0] = pd.NA
In [354]: s
Out[354]:
0 NaN
dtype: object
まとめ
-
None
そのものを格納するには、dtypeをobject
にする必要がある - 欠損値を格納できるdtypeの場合(
int64
,Int64
,datetime64
など)、None
はそのdtypeに合った欠損値(np.nan
,pd.NaT
,pd.NA
のいずれか)に変換される - dtypeが
bool
の場合は、dtypeがobject
になってNone
が格納されるときと、None
がnp.nan
に変換されるときがある
補足
pandas 1.4.4では、存在しない index にNone
を設定したときの挙動が異なる
pandas 1.4.4 では、存在するindexにNone
を設定するときと、存在しないindexにNone
を設定するときで、挙動が異なりました。
- Python 3.10.14
- pandas 1.4.4
- numpy 1.26.4
In [4]: s = pd.Series([1.2])
In [5]: s
Out[5]:
0 1.2
dtype: float64
In [6]: s[0] = None
In [7]: s
Out[7]:
0 NaN
dtype: float64
In [8]: s[1] = None
In [9]: s
Out[9]:
0 NaN
1 None
dtype: object
存在しないindex 1
に None
を設定すると、dtypeがobject
になり、None
は変換されずに格納されました。
なお、pandas 1.5.0以降では、存在するindexにNone
を設定するときと、存在しないindexにNone
を設定するときで、挙動は同じです。
In [380]: s = pd.Series([1.2])
In [381]: s
Out[381]:
0 1.2
dtype: float64
In [382]: s[0] = None
In [383]: s
Out[383]:
0 NaN
dtype: float64
In [384]: s[1] = None
In [385]: s
Out[385]:
0 NaN
1 NaN
dtype: float64
numpy.array
にNoneを設定したときの挙動
numpy.array
にNone
を設定したときの挙動は、pandas.Series
と微妙に異なります。注意しましょう。
In [394]: arr1 = np.array([1.2, None])
In [405]: arr1
Out[405]: array([1.2, None], dtype=object)
In [395]: arr1.dtype
Out[395]: dtype('O')
In [396]: arr2 = np.array([1.2, None], dtype="float64")
In [407]: arr2
Out[407]: array([1.2, nan])
In [397]: arr2.dtype
Out[397]: dtype('float64')
In [398]: arr3 = np.array([1.2])
In [399]: arr3.dtype
Out[399]: dtype('float64')
In [401]: arr3[0] = None
In [402]: arr3
Out[402]: array([nan])
In [403]: arr3.dtype
Out[403]: dtype('float64')
参考サイト