diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 49b2349851479..3ec6426cdb877 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -229,6 +229,7 @@ Bug Fixes ~~~~~~~~~ + Categorical ^^^^^^^^^^^ @@ -268,7 +269,7 @@ Numeric - Bug in error messages in :meth:`DataFrame.corr` and :meth:`Series.corr`. Added the possibility of using a callable. (:issue:`25729`) - Bug in :meth:`Series.divmod` and :meth:`Series.rdivmod` which would raise an (incorrect) ``ValueError`` rather than return a pair of :class:`Series` objects as result (:issue:`25557`) - Raises a helpful exception when a non-numeric index is sent to :meth:`interpolate` with methods which require numeric index. (:issue:`21662`) -- +- Bug in :meth:`~pandas.eval` when comparing floats with scalar operators, for example: ``x < -0.1`` (:issue:`25928`) - diff --git a/pandas/core/computation/expr.py b/pandas/core/computation/expr.py index 16795ea8c58e9..0488d27d89be4 100644 --- a/pandas/core/computation/expr.py +++ b/pandas/core/computation/expr.py @@ -418,11 +418,13 @@ def _maybe_transform_eq_ne(self, node, left=None, right=None): def _maybe_downcast_constants(self, left, right): f32 = np.dtype(np.float32) - if left.is_scalar and not right.is_scalar and right.return_type == f32: + if (left.is_scalar and hasattr(left, 'value') and + not right.is_scalar and right.return_type == f32): # right is a float32 array, left is a scalar name = self.env.add_tmp(np.float32(left.value)) left = self.term_type(name, self.env) - if right.is_scalar and not left.is_scalar and left.return_type == f32: + if (right.is_scalar and hasattr(right, 'value') and + not left.is_scalar and left.return_type == f32): # left is a float32 array, right is a scalar name = self.env.add_tmp(np.float32(right.value)) right = self.term_type(name, self.env) diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index f2d5069ccb5d0..3908a7f1f99aa 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -608,6 +608,16 @@ def test_unary_in_array(self): -False, False, ~False, +False, -37, 37, ~37, +37], dtype=np.object_)) + @pytest.mark.parametrize('dtype', [np.float32, np.float64]) + def test_float_comparison_bin_op(self, dtype): + # GH 16363 + df = pd.DataFrame({'x': np.array([0], dtype=dtype)}) + res = df.eval('x < -0.1') + assert res.values == np.array([False]) + + res = df.eval('-5 > x') + assert res.values == np.array([False]) + def test_disallow_scalar_bool_ops(self): exprs = '1 or 2', '1 and 2' exprs += 'a and b', 'a or b'