You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Previously, when dealing with a nullable dtype (e.g. ``Float64Dtype`` or ``int64[pyarrow]``), ``NaN`` was treated as interchangeable with :class:`NA` in some circumstances but not others. This was done to make adoption easier, but caused some confusion (:issue:`32265`). In 3.0, an option ``"mode.nan_is_na"`` (default ``True``) controls whether to treat ``NaN`` as equivalent to :class:`NA`.
555
+
Previously, when dealing with a nullable dtype (e.g. ``Float64Dtype`` or ``int64[pyarrow]``),
556
+
``NaN`` was treated as interchangeable with :class:`NA` in some circumstances but not others.
557
+
This was done to make adoption easier, but caused some confusion (:issue:`32265`).
558
+
In 3.0, this behaviour is made consistent to by default treat ``NaN`` as equivalent
559
+
to :class:`NA` in all cases.
556
560
557
-
With ``pd.set_option("mode.nan_is_na", True)`` (again, this is the default), ``NaN`` can be passed to constructors, ``__setitem__``, ``__contains__`` and be treated the same as :class:`NA`. The only change users will see is that arithmetic and ``np.ufunc`` operations that previously introduced ``NaN`` entries produce :class:`NA` entries instead:
561
+
By default, ``NaN`` can be passed to constructors, ``__setitem__``, ``__contains__``
562
+
and will be treated the same as :class:`NA`. The only change users will see is
563
+
that arithmetic and ``np.ufunc`` operations that previously introduced ``NaN``
564
+
entries produce :class:`NA` entries instead.
558
565
559
566
*Old behavior:*
560
567
561
568
.. code-block:: ipython
562
569
563
-
In [2]: ser = pd.Series([0, None], dtype=pd.Float64Dtype())
570
+
# NaN in input gets converted to NA
571
+
In [1]: ser = pd.Series([0, np.nan], dtype=pd.Float64Dtype())
572
+
In [2]: ser
573
+
Out[2]:
574
+
0 0.0
575
+
1 <NA>
576
+
dtype: Float64
577
+
# NaN produced by arithmetic (0/0) remained NaN
564
578
In [3]: ser / 0
565
579
Out[3]:
566
580
0 NaN
567
581
1 <NA>
568
582
dtype: Float64
583
+
# the NaN value is not considered as missing
584
+
In [4]: (ser / 0).isna()
585
+
Out[4]:
586
+
0 False
587
+
1 True
588
+
dtype: bool
569
589
570
590
*New behavior:*
571
591
572
592
.. ipython:: python
573
593
574
-
ser = pd.Series([0, None], dtype=pd.Float64Dtype())
594
+
ser = pd.Series([0, np.nan], dtype=pd.Float64Dtype())
595
+
ser
575
596
ser /0
597
+
(ser /0).isna()
576
598
577
-
By contrast, with ``pd.set_option("mode.nan_is_na", False)``, ``NaN`` is always considered distinct and specifically as a floating-point value, so cannot be used with integer dtypes:
599
+
In the future, the intention is to consider ``NaN`` and :class:`NA` as distinct
600
+
values, and an option to control this behaviour is added in 3.0 through
601
+
``pd.options.future.distinguish_nan_and_na``. When enabled, ``NaN`` is always
602
+
considered distinct and specifically as a floating-point value. As a consequence,
603
+
it cannot be used with integer dtypes.
578
604
579
605
*Old behavior:*
580
606
@@ -588,13 +614,21 @@ By contrast, with ``pd.set_option("mode.nan_is_na", False)``, ``NaN`` is always
588
614
589
615
.. ipython:: python
590
616
591
-
pd.set_option("mode.nan_is_na", False)
592
-
ser = pd.Series([1, np.nan], dtype=pd.Float64Dtype())
593
-
ser[1]
617
+
with pd.option_context("future.distinguish_nan_and_na", True):
618
+
ser = pd.Series([1, np.nan], dtype=pd.Float64Dtype())
619
+
print(ser[1])
620
+
621
+
If we had passed ``pd.Int64Dtype()`` or ``"int64[pyarrow]"`` for the dtype in
622
+
the latter example, this would raise, as a float ``NaN`` cannot be held by an
623
+
integer dtype.
594
624
595
-
If we had passed ``pd.Int64Dtype()`` or ``"int64[pyarrow]"`` for the dtype in the latter example, this would raise, as a float ``NaN`` cannot be held by an integer dtype.
625
+
With ``"future.distinguish_nan_and_na"`` enabled, ``ser.to_numpy()`` (and
626
+
``frame.values`` and ``np.asarray(obj)``) will convert to ``object`` dtype if
627
+
:class:`NA` entries are present, where before they would coerce to
628
+
``NaN``. To retain a float numpy dtype, explicitly pass ``na_value=np.nan``
629
+
to :meth:`Series.to_numpy`.
596
630
597
-
With ``"mode.nan_is_na"`` set to ``False``, ``ser.to_numpy()`` (and ``frame.values`` and ``np.asarray(obj)``) will convert to ``object`` dtype if :class:`NA` entries are present, where before they would coerce to ``NaN``. To retain a float numpy dtype, explicitly pass ``na_value=np.nan`` to :meth:`Series.to_numpy`.
631
+
Note that the option is experimental and subject to change in future releases.
598
632
599
633
The ``__module__`` attribute now points to public modules
- Bug in :class:`DataFrame` and :class:`Series` ``repr`` of :py:class:`collections.abc.Mapping` elements. (:issue:`57915`)
1229
+
- Bug in :meth:`DataFrame.to_hdf` and :func:`read_hdf` with ``timedelta64`` dtypes with non-nanosecond resolution failing to round-trip correctly (:issue:`63239`)
1195
1230
- Fix bug in ``on_bad_lines`` callable when returning too many fields: now emits
1196
1231
``ParserWarning`` and truncates extra fields regardless of ``index_col`` (:issue:`61837`)
1197
1232
- Bug in :func:`pandas.json_normalize` inconsistently handling non-dict items in ``data`` when ``max_level`` was set. The function will now raise a ``TypeError`` if ``data`` is a list containing non-dict items (:issue:`62829`)
@@ -1249,6 +1284,7 @@ Plotting
1249
1284
- Bug in :meth:`Series.plot` preventing a line and bar from being aligned on the same plot (:issue:`61161`)
1250
1285
- Bug in :meth:`Series.plot` preventing a line and scatter plot from being aligned (:issue:`61005`)
1251
1286
- Bug in :meth:`Series.plot` with ``kind="pie"`` with :class:`ArrowDtype` (:issue:`59192`)
1287
+
- Bug in plotting with a :class:`TimedeltaIndex` with non-nanosecond resolution displaying incorrect labels (:issue:`63237`)
0 commit comments