Skip to content

Fix : #58748 BUG: eval fails for ExtensionArray #58793

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 12, 2024
Merged
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ Styler
Other
^^^^^
- Bug in :class:`DataFrame` when passing a ``dict`` with a NA scalar and ``columns`` that would always return ``np.nan`` (:issue:`57205`)
- Bug in :func:`eval` on :class:`ExtensionArray` on including division ``/`` failed with a ``TypeError``. (:issue:`58748`)
- Bug in :func:`eval` where the names of the :class:`Series` were not preserved when using ``engine="numexpr"``. (:issue:`10239`)
- Bug in :func:`unique` on :class:`Index` not always returning :class:`Index` (:issue:`57043`)
- Bug in :meth:`DataFrame.eval` and :meth:`DataFrame.query` which caused an exception when using NumPy attributes via ``@`` notation, e.g., ``df.eval("@np.floor(a)")``. (:issue:`58041`)
Expand Down
9 changes: 4 additions & 5 deletions pandas/core/computation/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from pandas.core.dtypes.common import (
is_list_like,
is_numeric_dtype,
is_scalar,
)

Expand Down Expand Up @@ -508,10 +509,6 @@ def _disallow_scalar_only_bool_ops(self) -> None:
raise NotImplementedError("cannot evaluate scalar only bool ops")


def isnumeric(dtype) -> bool:
return issubclass(np.dtype(dtype).type, np.number)


class Div(BinOp):
"""
Div operator to special case casting.
Expand All @@ -525,7 +522,9 @@ class Div(BinOp):
def __init__(self, lhs, rhs) -> None:
super().__init__("/", lhs, rhs)

if not isnumeric(lhs.return_type) or not isnumeric(rhs.return_type):
if not is_numeric_dtype(lhs.return_type) or not is_numeric_dtype(
rhs.return_type
):
raise TypeError(
f"unsupported operand type(s) for {self.op}: "
f"'{lhs.return_type}' and '{rhs.return_type}'"
Expand Down
7 changes: 7 additions & 0 deletions pandas/tests/frame/test_query_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ def test_eval_simple(self, engine, parser):
expected = df["a"]
tm.assert_series_equal(expected, res)

def test_extension_array_eval(self, engine, parser):
# GH#58748
df = DataFrame({"a": pd.array([1, 2, 3]), "b": pd.array([4, 5, 6])})
result = df.eval("a / b", engine=engine, parser=parser)
expected = Series([0.25, 0.40, 0.50])
tm.assert_series_equal(result, expected)


class TestDataFrameQueryWithMultiIndex:
def test_query_with_named_multiindex(self, parser, engine):
Expand Down
Loading