Skip to content

Commit a58dcfc

Browse files
yuanx749noatamir
authored andcommitted
BUG: Fix bug in pd.eval when UnaryOp in function (pandas-dev#48511)
* Fix bug in pd.eval when negative value in function * Fix test * Add whatsnew * Change name check
1 parent ad7dc7a commit a58dcfc

File tree

3 files changed

+17
-2
lines changed

3 files changed

+17
-2
lines changed

doc/source/whatsnew/v1.6.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ Numeric
148148
Conversion
149149
^^^^^^^^^^
150150
- Bug in constructing :class:`Series` with ``int64`` dtype from a string list raising instead of casting (:issue:`44923`)
151+
- Bug in :meth:`DataFrame.eval` incorrectly raising an ``AttributeError`` when there are negative values in function call (:issue:`46471`)
151152
-
152153

153154
Strings

pandas/core/computation/expr.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ def visit_Call(self, node, side=None, **kwargs):
693693

694694
else:
695695

696-
new_args = [self.visit(arg).value for arg in node.args]
696+
new_args = [self.visit(arg)(self.env) for arg in node.args]
697697

698698
for key in node.keywords:
699699
if not isinstance(key, ast.keyword):
@@ -704,7 +704,7 @@ def visit_Call(self, node, side=None, **kwargs):
704704
)
705705

706706
if key.arg:
707-
kwargs[key.arg] = self.visit(key.value).value
707+
kwargs[key.arg] = self.visit(key.value)(self.env)
708708

709709
name = self.env.add_tmp(res(*new_args, **kwargs))
710710
return self.term_type(name=name, env=self.env)

pandas/tests/computation/test_eval.py

+14
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,20 @@ def test_float_comparison_bin_op(self, dtype, expr):
600600
res = df.eval(expr)
601601
assert res.values == np.array([False])
602602

603+
def test_unary_in_function(self):
604+
# GH 46471
605+
df = DataFrame({"x": [0, 1, np.nan]})
606+
607+
result = df.eval("x.fillna(-1)")
608+
expected = df.x.fillna(-1)
609+
# column name becomes None if using numexpr
610+
# only check names when the engine is not numexpr
611+
tm.assert_series_equal(result, expected, check_names=not USE_NUMEXPR)
612+
613+
result = df.eval("x.shift(1, fill_value=-1)")
614+
expected = df.x.shift(1, fill_value=-1)
615+
tm.assert_series_equal(result, expected, check_names=not USE_NUMEXPR)
616+
603617
@pytest.mark.parametrize(
604618
"ex",
605619
(

0 commit comments

Comments
 (0)