Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/pandas-dev/pandas into re…
Browse files Browse the repository at this point in the history
…f-blockwise-3
  • Loading branch information
jbrockmendel committed Aug 21, 2020
2 parents c632c9f + 9468071 commit 9e64be3
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 14 deletions.
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.1.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Fixed regressions

Bug fixes
~~~~~~~~~

- Bug in :meth:`DataFrame.eval` with ``object`` dtype column binary operations (:issue:`35794`)
-
-

Expand Down
14 changes: 11 additions & 3 deletions pandas/core/computation/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,13 +481,21 @@ def stringify(value):
self.lhs.update(v)

def _disallow_scalar_only_bool_ops(self):
rhs = self.rhs
lhs = self.lhs

# GH#24883 unwrap dtype if necessary to ensure we have a type object
rhs_rt = rhs.return_type
rhs_rt = getattr(rhs_rt, "type", rhs_rt)
lhs_rt = lhs.return_type
lhs_rt = getattr(lhs_rt, "type", lhs_rt)
if (
(self.lhs.is_scalar or self.rhs.is_scalar)
(lhs.is_scalar or rhs.is_scalar)
and self.op in _bool_ops_dict
and (
not (
issubclass(self.rhs.return_type, (bool, np.bool_))
and issubclass(self.lhs.return_type, (bool, np.bool_))
issubclass(rhs_rt, (bool, np.bool_))
and issubclass(lhs_rt, (bool, np.bool_))
)
)
):
Expand Down
27 changes: 17 additions & 10 deletions pandas/core/window/rolling.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from pandas._libs.tslibs import BaseOffset, to_offset
import pandas._libs.window.aggregations as window_aggregations
from pandas._typing import ArrayLike, Axis, FrameOrSeries, Scalar
from pandas._typing import ArrayLike, Axis, FrameOrSeries, Label
from pandas.compat._optional import import_optional_dependency
from pandas.compat.numpy import function as nv
from pandas.util._decorators import Appender, Substitution, cache_readonly, doc
Expand Down Expand Up @@ -381,21 +381,31 @@ def _wrap_result(self, result, block=None, obj=None):
return type(obj)(result, index=index, columns=block.columns)
return result

def _wrap_results(self, results, blocks, obj, exclude=None) -> FrameOrSeries:
def _wrap_results(self, results, obj, skipped: List[int]) -> FrameOrSeries:
"""
Wrap the results.
Parameters
----------
results : list of ndarrays
blocks : list of blocks
obj : conformed data (may be resampled)
exclude: list of columns to exclude, default to None
skipped: List[int]
Indices of blocks that are skipped.
"""
from pandas import Series, concat

exclude: List[Label] = []
if obj.ndim == 2:
orig_blocks = list(obj._to_dict_of_blocks(copy=False).values())
for i in skipped:
exclude.extend(orig_blocks[i].columns)
else:
orig_blocks = [obj]

kept_blocks = [blk for i, blk in enumerate(orig_blocks) if i not in skipped]

final = []
for result, block in zip(results, blocks):
for result, block in zip(results, kept_blocks):

result = self._wrap_result(result, block=block, obj=obj)
if result.ndim == 1:
Expand Down Expand Up @@ -491,24 +501,21 @@ def _apply_blockwise(

skipped: List[int] = []
results: List[ArrayLike] = []
exclude: List[Scalar] = []
for i, b in enumerate(blocks):
try:
values = self._prep_values(b.values)

except (TypeError, NotImplementedError) as err:
if isinstance(obj, ABCDataFrame):
skipped.append(i)
exclude.extend(b.columns)
continue
else:
raise DataError("No numeric types to aggregate") from err

result = homogeneous_func(values)
results.append(result)

block_list = [blk for i, blk in enumerate(blocks) if i not in skipped]
return self._wrap_results(results, block_list, obj, exclude)
return self._wrap_results(results, obj, skipped)

def _apply(
self,
Expand Down Expand Up @@ -1283,7 +1290,7 @@ def count(self):
).sum()
results.append(result)

return self._wrap_results(results, blocks, obj)
return self._wrap_results(results, obj, skipped=[])

_shared_docs["apply"] = dedent(
r"""
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 @@ -160,6 +160,13 @@ 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_object_dtype_binop(self):
# GH#24883
df = pd.DataFrame({"a1": ["Y", "N"]})
res = df.eval("c = ((a1 == 'Y') & True)")
expected = pd.DataFrame({"a1": ["Y", "N"], "c": [True, False]})
tm.assert_frame_equal(res, expected)


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

0 comments on commit 9e64be3

Please sign in to comment.