Skip to content

Commit 4d697b7

Browse files
committed
Fix #22903 for lib.is_scalar missing PEP 3141 numbers
1 parent deb7b4d commit 4d697b7

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

doc/source/whatsnew/v0.24.0.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ For situations where you need an ``ndarray`` of ``Interval`` objects, use
465465
np.asarray(idx)
466466
idx.values.astype(object)
467467
468+
468469
.. _whatsnew_0240.api.timezone_offset_parsing:
469470

470471
Parsing Datetime Strings with Timezone Offsets
@@ -1471,6 +1472,7 @@ Other
14711472
- :meth:`DataFrame.nlargest` and :meth:`DataFrame.nsmallest` now returns the correct n values when keep != 'all' also when tied on the first columns (:issue:`22752`)
14721473
- :meth:`~pandas.io.formats.style.Styler.bar` now also supports tablewise application (in addition to rowwise and columnwise) with ``axis=None`` and setting clipping range with ``vmin`` and ``vmax`` (:issue:`21548` and :issue:`21526`). ``NaN`` values are also handled properly.
14731474
- Logical operations ``&, |, ^`` between :class:`Series` and :class:`Index` will no longer raise ``ValueError`` (:issue:`22092`)
1475+
- Checking PEP 3141 numbers in :func:`~pandas.api.types.is_scalar` function returns ``True`` (:issue:`22903`)
14741476
- Bug in :meth:`DataFrame.combine_first` in which column types were unexpectedly converted to float (:issue:`20699`)
14751477

14761478
.. _whatsnew_0.24.0.contributors:
@@ -1479,3 +1481,4 @@ Contributors
14791481
~~~~~~~~~~~~
14801482

14811483
.. contributors:: v0.23.4..HEAD
1484+

pandas/_libs/lib.pyx

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# -*- coding: utf-8 -*-
22
from decimal import Decimal
3+
from fractions import Fraction
4+
from numbers import Number
5+
36
import sys
47

58
import cython
@@ -15,7 +18,6 @@ from cpython.datetime cimport (PyDateTime_Check, PyDate_Check,
1518
PyDateTime_IMPORT)
1619
PyDateTime_IMPORT
1720

18-
1921
import numpy as np
2022
cimport numpy as cnp
2123
from numpy cimport (ndarray, PyArray_GETITEM,
@@ -104,7 +106,10 @@ def memory_usage_of_objects(arr: object[:]) -> int64_t:
104106
def is_scalar(val: object) -> bool:
105107
"""
106108
Return True if given value is scalar.
107-
109+
110+
Parameters
111+
----------
112+
val : input argument of any type
108113
This includes:
109114
- numpy array scalar (e.g. np.int64)
110115
- Python builtin numerics
@@ -116,12 +121,42 @@ def is_scalar(val: object) -> bool:
116121
- instances of decimal.Decimal
117122
- Interval
118123
- DateOffset
124+
- Fraction
125+
- Number
119126

127+
Returns
128+
-------
129+
True if the given value is scalar, False otherwise.
130+
131+
Examples
132+
--------
133+
>>> dt = pd.datetime.datetime(2018, 10, 3)
134+
>>> pd.is_scalar(dt)
135+
True
136+
137+
>>> pd.api.types.is_scalar([2, 3])
138+
False
139+
140+
>>> pd.api.types.is_scalar({0:1, 2:3})
141+
False
142+
143+
>>> pd.api.types.is_scalar((0, 2))
144+
False
145+
146+
pandas supports PEP 3141 numbers:
147+
148+
>>> from fractions import Fraction
149+
>>> pd.api.types.is_scalar(Fraction(3, 5))
150+
True
151+
152+
>>> from numbers import Number
153+
>>> pd.api.types.is_scalar(Number())
154+
True
120155
"""
121156

122157
return (cnp.PyArray_IsAnyScalar(val)
123158
# As of numpy-1.9, PyArray_IsAnyScalar misses bytearrays on Py3.
124-
or isinstance(val, bytes)
159+
or isinstance(val,(bytes, Fraction, Number))
125160
# We differ from numpy (as of 1.10), which claims that None is
126161
# not scalar in np.isscalar().
127162
or val is None
@@ -133,7 +168,6 @@ def is_scalar(val: object) -> bool:
133168
or is_interval(val)
134169
or util.is_offset_object(val))
135170

136-
137171
def item_from_zerodim(val: object) -> object:
138172
"""
139173
If the value is a zerodim array, return the item it contains.

pandas/tests/dtypes/test_inference.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
import re
1111
from datetime import datetime, date, timedelta, time
1212
from decimal import Decimal
13+
from numbers import Number
14+
from fractions import Fraction
1315
import numpy as np
1416
import pytz
1517
import pytest
16-
1718
import pandas as pd
1819
from pandas._libs import lib, iNaT, missing as libmissing
1920
from pandas import (Series, Index, DataFrame, Timedelta,
@@ -1183,6 +1184,8 @@ def test_is_scalar_builtin_scalars(self):
11831184
assert is_scalar(None)
11841185
assert is_scalar(True)
11851186
assert is_scalar(False)
1187+
assert is_scalar(Number())
1188+
assert is_scalar(Fraction())
11861189
assert is_scalar(0.)
11871190
assert is_scalar(np.nan)
11881191
assert is_scalar('foobar')
@@ -1247,7 +1250,6 @@ def test_is_scalar_pandas_containers(self):
12471250
assert not is_scalar(Index([]))
12481251
assert not is_scalar(Index([1]))
12491252

1250-
12511253
def test_datetimeindex_from_empty_datetime64_array():
12521254
for unit in ['ms', 'us', 'ns']:
12531255
idx = DatetimeIndex(np.array([], dtype='datetime64[%s]' % unit))

0 commit comments

Comments
 (0)