diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index a940a1a1c0a08..0e0328b964c35 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -1000,6 +1000,7 @@ Other - Bug in :meth:`DataFrame.diff` when passing a NumPy integer object instead of an ``int`` object (:issue:`44572`) - Bug in :meth:`Series.replace` raising ``ValueError`` when using ``regex=True`` with a :class:`Series` containing ``np.nan`` values (:issue:`43344`) - Bug in :meth:`DataFrame.to_records` where an incorrect ``n`` was used when missing names were replaced by ``level_n`` (:issue:`44818`) +- Bug in :meth:`DataFrame.eval` where ``resolvers`` argument was overriding the default resolvers (:issue:`34966`) .. ***DO NOT USE THIS SECTION*** diff --git a/pandas/core/frame.py b/pandas/core/frame.py index a39c1b0bf43f2..af504263e3888 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -4224,15 +4224,13 @@ def eval(self, expr: str, inplace: bool = False, **kwargs): from pandas.core.computation.eval import eval as _eval inplace = validate_bool_kwarg(inplace, "inplace") - resolvers = kwargs.pop("resolvers", None) kwargs["level"] = kwargs.pop("level", 0) + 1 - if resolvers is None: - index_resolvers = self._get_index_resolvers() - column_resolvers = self._get_cleaned_column_resolvers() - resolvers = column_resolvers, index_resolvers + index_resolvers = self._get_index_resolvers() + column_resolvers = self._get_cleaned_column_resolvers() + resolvers = column_resolvers, index_resolvers if "target" not in kwargs: kwargs["target"] = self - kwargs["resolvers"] = kwargs.get("resolvers", ()) + tuple(resolvers) + kwargs["resolvers"] = tuple(kwargs.get("resolvers", ())) + resolvers return _eval(expr, inplace=inplace, **kwargs) diff --git a/pandas/tests/frame/test_query_eval.py b/pandas/tests/frame/test_query_eval.py index 331c21de8e4bd..558ba0424e481 100644 --- a/pandas/tests/frame/test_query_eval.py +++ b/pandas/tests/frame/test_query_eval.py @@ -165,6 +165,17 @@ def test_eval_resolvers_as_list(self): assert df.eval("a + b", resolvers=[dict1, dict2]) == dict1["a"] + dict2["b"] assert pd.eval("a + b", resolvers=[dict1, dict2]) == dict1["a"] + dict2["b"] + def test_eval_resolvers_combined(self): + # GH 34966 + df = DataFrame(np.random.randn(10, 2), columns=list("ab")) + dict1 = {"c": 2} + + # Both input and default index/column resolvers should be usable + result = df.eval("a + b * c", resolvers=[dict1]) + + expected = df["a"] + df["b"] * dict1["c"] + tm.assert_series_equal(result, expected) + def test_eval_object_dtype_binop(self): # GH#24883 df = DataFrame({"a1": ["Y", "N"]})