diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index a0d33cb513722..1379a13f0e42a 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -932,6 +932,8 @@ Conversion - Bug in :meth:`DataFrame.to_dict` for ``orient="list"`` or ``orient="index"`` was not returning native types (:issue:`46751`) - Bug in :meth:`DataFrame.apply` that returns a :class:`DataFrame` instead of a :class:`Series` when applied to an empty :class:`DataFrame` and ``axis=1`` (:issue:`39111`) - Bug when inferring the dtype from an iterable that is *not* a NumPy ``ndarray`` consisting of all NumPy unsigned integer scalars did not result in an unsigned integer dtype (:issue:`47294`) +- Bug in :meth:`DataFrame.eval` when pandas objects (e.g. ``'Timestamp'``) were column names (:issue:`44603`) +- Strings ^^^^^^^ diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py index e331fc89f69b7..cb7b33e40d989 100644 --- a/pandas/core/computation/ops.py +++ b/pandas/core/computation/ops.py @@ -99,7 +99,14 @@ def evaluate(self, *args, **kwargs) -> Term: return self def _resolve_name(self): - res = self.env.resolve(self.local_name, is_local=self.is_local) + local_name = str(self.local_name) + is_local = self.is_local + if local_name in self.env.scope and isinstance( + self.env.scope[local_name], type + ): + is_local = False + + res = self.env.resolve(local_name, is_local=is_local) self.update(res) if hasattr(res, "ndim") and res.ndim > 2: diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index b0ad2f69a75b9..672a87edbad66 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -49,6 +49,7 @@ _binary_ops_dict, _unary_math_ops, ) +from pandas.core.computation.scope import DEFAULT_GLOBALS @pytest.fixture( @@ -1890,6 +1891,27 @@ def test_negate_lt_eq_le(engine, parser): tm.assert_frame_equal(result, expected) +@pytest.mark.parametrize( + "column", + DEFAULT_GLOBALS.keys(), +) +def test_eval_no_support_column_name(request, column): + # GH 44603 + if column in ["True", "False", "inf", "Inf"]: + request.node.add_marker( + pytest.mark.xfail( + raises=KeyError, + reason=f"GH 47859 DataFrame eval not supported with {column}", + ) + ) + + df = DataFrame(np.random.randint(0, 100, size=(10, 2)), columns=[column, "col1"]) + expected = df[df[column] > 6] + result = df.query(f"{column}>6") + + tm.assert_frame_equal(result, expected) + + class TestValidate: @pytest.mark.parametrize("value", [1, "True", [1, 2, 3], 5.0]) def test_validate_bool_args(self, value):