0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

`pandas.Series`に`None`を設定したときの挙動

Last updated at Posted at 2024-11-20

環境

  • Python 3.12.4
  • pandas 2.2.3
  • numpy 1.26.4

概要

pandas.Seriesnp.nanNoneどちらを設定すればよいのか、悩むときがありました。
そこで、pandas.SeriesNoneを格納しようとしたときに、どのような挙動になるかを確認しました。

結果

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.nanfloatなので、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に変換されます。

NoneTrueを格納する(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になったようです。

NoneTrueを格納する(dtypeを指定する)

In [350]: pd.Series([None, True], dtype="bool")
Out[350]:
0    False
1     True
dtype: bool

dtypeがboolの場合欠損値を格納できないので、Nonebool(None)の結果Falseに変換されました。

dtype="Int64"を指定する

In [331]: pd.Series([None], dtype="Int64")
Out[331]:
0    <NA>
dtype: Int64

値の代入

dtypeがint64pandas.SeriesNoneを設定

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がInt64pandas.SeriesNoneを設定

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がdatetime64pandas.SeriesNoneを設定

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がobjectpandas.SeriesNoneを設定

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がboolpandas.SeriesNoneを設定

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が格納されるときと、Nonenp.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 1Noneを設定すると、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.arrayNoneを設定したときの挙動は、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')

参考サイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?