Skip to content

Commit 7f2f465

Browse files
authored
BUG: Add is_any_real_numeric_dtype to solve discrepancy between Index.is_numeric() and is_numeric_dtype() (#51160)
1 parent d8a1a0d commit 7f2f465

File tree

12 files changed

+47
-25
lines changed

12 files changed

+47
-25
lines changed

ci/code_checks.sh

+1
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
590590
pandas.Series.sparse.sp_values \
591591
pandas.Timestamp.fromtimestamp \
592592
pandas.api.types.infer_dtype \
593+
pandas.api.types.is_any_real_numeric_dtype \
593594
pandas.api.types.is_bool_dtype \
594595
pandas.api.types.is_categorical_dtype \
595596
pandas.api.types.is_complex_dtype \

doc/source/reference/arrays.rst

+1
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ Data type introspection
653653
.. autosummary::
654654
:toctree: api/
655655

656+
api.types.is_any_real_numeric_dtype
656657
api.types.is_bool_dtype
657658
api.types.is_categorical_dtype
658659
api.types.is_complex_dtype

doc/source/whatsnew/v2.0.0.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,7 @@ Other API changes
760760
- The levels of the index of the :class:`Series` returned from ``Series.sparse.from_coo`` now always have dtype ``int32``. Previously they had dtype ``int64`` (:issue:`50926`)
761761
- :func:`to_datetime` with ``unit`` of either "Y" or "M" will now raise if a sequence contains a non-round ``float`` value, matching the ``Timestamp`` behavior (:issue:`50301`)
762762
- The methods :meth:`Series.round`, :meth:`DataFrame.__invert__`, :meth:`Series.__invert__`, :meth:`DataFrame.swapaxes`, :meth:`DataFrame.first`, :meth:`DataFrame.last`, :meth:`Series.first`, :meth:`Series.last` and :meth:`DataFrame.align` will now always return new objects (:issue:`51032`)
763+
- Added :func:`pandas.api.types.is_any_real_numeric_dtype` to check for real numeric dtypes (:issue:`51152`)
763764

764765
.. ---------------------------------------------------------------------------
765766
.. _whatsnew_200.deprecations:
@@ -774,7 +775,7 @@ Deprecations
774775
- :meth:`Index.is_integer` has been deprecated. Use :func:`pandas.api.types.is_integer_dtype` instead (:issue:`50042`)
775776
- :meth:`Index.is_floating` has been deprecated. Use :func:`pandas.api.types.is_float_dtype` instead (:issue:`50042`)
776777
- :meth:`Index.holds_integer` has been deprecated. Use :func:`pandas.api.types.infer_dtype` instead (:issue:`50243`)
777-
- :meth:`Index.is_numeric` has been deprecated. Use :func:`pandas.api.types.is_numeric_dtype` instead (:issue:`50042`)
778+
- :meth:`Index.is_numeric` has been deprecated. Use :func:`pandas.api.types.is_any_real_numeric_dtype` instead (:issue:`50042`,:issue:`51152`)
778779
- :meth:`Index.is_categorical` has been deprecated. Use :func:`pandas.api.types.is_categorical_dtype` instead (:issue:`50042`)
779780
- :meth:`Index.is_object` has been deprecated. Use :func:`pandas.api.types.is_object_dtype` instead (:issue:`50042`)
780781
- :meth:`Index.is_interval` has been deprecated. Use :func:`pandas.api.types.is_intterval_dtype` instead (:issue:`50042`)

pandas/core/arrays/categorical.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from pandas.core.dtypes.common import (
4848
ensure_int64,
4949
ensure_platform_int,
50-
is_any_numeric_dtype,
50+
is_any_real_numeric_dtype,
5151
is_bool_dtype,
5252
is_categorical_dtype,
5353
is_datetime64_dtype,
@@ -596,7 +596,7 @@ def _from_inferred_categories(
596596

597597
if known_categories:
598598
# Convert to a specialized type with `dtype` if specified.
599-
if is_any_numeric_dtype(dtype.categories):
599+
if is_any_real_numeric_dtype(dtype.categories):
600600
cats = to_numeric(inferred_categories, errors="coerce")
601601
elif is_datetime64_dtype(dtype.categories):
602602
cats = to_datetime(inferred_categories, errors="coerce")
@@ -1752,7 +1752,7 @@ def _values_for_rank(self):
17521752
if mask.any():
17531753
values = values.astype("float64")
17541754
values[mask] = np.nan
1755-
elif is_any_numeric_dtype(self.categories):
1755+
elif is_any_real_numeric_dtype(self.categories):
17561756
values = np.array(self)
17571757
else:
17581758
# reorder the categories (so rank can use the float codes)

pandas/core/dtypes/api.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from pandas.core.dtypes.common import (
2+
is_any_real_numeric_dtype,
23
is_array_like,
34
is_bool,
45
is_bool_dtype,
@@ -41,6 +42,7 @@
4142
)
4243

4344
__all__ = [
45+
"is_any_real_numeric_dtype",
4446
"is_array_like",
4547
"is_bool",
4648
"is_bool_dtype",

pandas/core/dtypes/common.py

+13-11
Original file line numberDiff line numberDiff line change
@@ -1161,9 +1161,9 @@ def is_numeric_dtype(arr_or_dtype) -> bool:
11611161
)
11621162

11631163

1164-
def is_any_numeric_dtype(arr_or_dtype) -> bool:
1164+
def is_any_real_numeric_dtype(arr_or_dtype) -> bool:
11651165
"""
1166-
Check whether the provided array or dtype is of a real number dtype
1166+
Check whether the provided array or dtype is of a real number dtype.
11671167
11681168
Parameters
11691169
----------
@@ -1173,19 +1173,21 @@ def is_any_numeric_dtype(arr_or_dtype) -> bool:
11731173
Returns
11741174
-------
11751175
boolean
1176-
Whether or not the array or dtype is of a real number dtype
1176+
Whether or not the array or dtype is of a real number dtype.
11771177
11781178
Examples
1179-
-------
1180-
>>> is_any_numeric_dtype(str)
1181-
False
1182-
>>> is_any_numeric_dtype(int)
1179+
--------
1180+
>>> is_any_real_numeric_dtype(int)
11831181
True
1184-
>>> is_any_numeric_dtype(float)
1182+
>>> is_any_real_numeric_dtype(float)
11851183
True
1186-
>>> is_any_numeric_dtype(complex(1,2))
1184+
>>> is_any_real_numeric_dtype(object)
1185+
False
1186+
>>> is_any_real_numeric_dtype(str)
1187+
False
1188+
>>> is_any_real_numeric_dtype(complex(1, 2))
11871189
False
1188-
>>> is_any_numeric_dtype(bool)
1190+
>>> is_any_real_numeric_dtype(bool)
11891191
False
11901192
"""
11911193
return (
@@ -1721,6 +1723,7 @@ def is_all_strings(value: ArrayLike) -> bool:
17211723
"is_1d_only_ea_obj",
17221724
"is_all_strings",
17231725
"is_any_int_dtype",
1726+
"is_any_real_numeric_dtype",
17241727
"is_array_like",
17251728
"is_bool",
17261729
"is_bool_dtype",
@@ -1749,7 +1752,6 @@ def is_all_strings(value: ArrayLike) -> bool:
17491752
"is_nested_list_like",
17501753
"is_number",
17511754
"is_numeric_dtype",
1752-
"is_any_numeric_dtype",
17531755
"is_object_dtype",
17541756
"is_period_dtype",
17551757
"is_re",

pandas/core/indexes/base.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
ensure_int64,
8989
ensure_object,
9090
ensure_platform_int,
91-
is_any_numeric_dtype,
91+
is_any_real_numeric_dtype,
9292
is_bool_dtype,
9393
is_categorical_dtype,
9494
is_dtype_equal,
@@ -2429,7 +2429,7 @@ def is_numeric(self) -> bool:
24292429
"""
24302430
warnings.warn(
24312431
f"{type(self).__name__}.is_numeric is deprecated. "
2432-
"Use pandas.api.types.is_numeric_dtype instead",
2432+
"Use pandas.api.types.is_any_real_numeric_dtype instead",
24332433
FutureWarning,
24342434
stacklevel=find_stack_level(),
24352435
)
@@ -6029,8 +6029,8 @@ def _should_compare(self, other: Index) -> bool:
60296029
Check if `self == other` can ever have non-False entries.
60306030
"""
60316031

6032-
if (is_bool_dtype(other) and is_any_numeric_dtype(self)) or (
6033-
is_bool_dtype(self) and is_any_numeric_dtype(other)
6032+
if (is_bool_dtype(other) and is_any_real_numeric_dtype(self)) or (
6033+
is_bool_dtype(self) and is_any_real_numeric_dtype(other)
60346034
):
60356035
# GH#16877 Treat boolean labels passed to a numeric index as not
60366036
# found. Without this fix False and True would be treated as 0 and 1

pandas/plotting/_matplotlib/core.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from pandas.util._exceptions import find_stack_level
2828

2929
from pandas.core.dtypes.common import (
30-
is_any_numeric_dtype,
30+
is_any_real_numeric_dtype,
3131
is_categorical_dtype,
3232
is_extension_array_dtype,
3333
is_float,
@@ -841,7 +841,7 @@ def _get_xticks(self, convert_period: bool = False):
841841
if convert_period and isinstance(index, ABCPeriodIndex):
842842
self.data = self.data.reindex(index=index.sort_values())
843843
x = self.data.index.to_timestamp()._mpl_repr()
844-
elif is_any_numeric_dtype(index):
844+
elif is_any_real_numeric_dtype(index):
845845
# Matplotlib supports numeric values or datetime objects as
846846
# xaxis values. Taking LBYL approach here, by the time
847847
# matplotlib raises exception when using non numeric/datetime

pandas/tests/api/test_types.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
class TestTypes(Base):
99

1010
allowed = [
11+
"is_any_real_numeric_dtype",
1112
"is_bool",
1213
"is_bool_dtype",
1314
"is_categorical_dtype",

pandas/tests/dtypes/test_common.py

+14
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,20 @@ def _is_numeric(self) -> bool:
558558
assert com.is_numeric_dtype(MyNumericDType())
559559

560560

561+
def test_is_any_real_numeric_dtype():
562+
assert not com.is_any_real_numeric_dtype(str)
563+
assert not com.is_any_real_numeric_dtype(bool)
564+
assert not com.is_any_real_numeric_dtype(complex)
565+
assert not com.is_any_real_numeric_dtype(object)
566+
assert not com.is_any_real_numeric_dtype(np.datetime64)
567+
assert not com.is_any_real_numeric_dtype(np.array(["a", "b", complex(1, 2)]))
568+
assert not com.is_any_real_numeric_dtype(pd.DataFrame([complex(1, 2), True]))
569+
570+
assert com.is_any_real_numeric_dtype(int)
571+
assert com.is_any_real_numeric_dtype(float)
572+
assert com.is_any_real_numeric_dtype(np.array([1, 2.5]))
573+
574+
561575
def test_is_float_dtype():
562576
assert not com.is_float_dtype(str)
563577
assert not com.is_float_dtype(int)

pandas/tests/indexes/multi/test_equivalence.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import numpy as np
22
import pytest
33

4-
from pandas.core.dtypes.common import is_any_numeric_dtype
4+
from pandas.core.dtypes.common import is_any_real_numeric_dtype
55

66
import pandas as pd
77
from pandas import (
@@ -255,7 +255,7 @@ def test_is_all_dates(idx):
255255

256256
def test_is_numeric(idx):
257257
# MultiIndex is never numeric
258-
assert not is_any_numeric_dtype(idx)
258+
assert not is_any_real_numeric_dtype(idx)
259259

260260

261261
def test_multiindex_compare():

pandas/tests/indexes/test_base.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from pandas.util._test_decorators import async_mark
2020

2121
from pandas.core.dtypes.common import (
22-
is_any_numeric_dtype,
22+
is_any_real_numeric_dtype,
2323
is_numeric_dtype,
2424
is_object_dtype,
2525
)
@@ -659,7 +659,7 @@ def test_append_empty_preserve_name(self, name, expected):
659659
indirect=["index"],
660660
)
661661
def test_is_numeric(self, index, expected):
662-
assert is_any_numeric_dtype(index) is expected
662+
assert is_any_real_numeric_dtype(index) is expected
663663

664664
@pytest.mark.parametrize(
665665
"index, expected",

0 commit comments

Comments
 (0)