Skip to content

BUG: Series.__rfloordiv__ with list/tuple #44674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ Timezones

Numeric
^^^^^^^
- Bug in floor-dividing a list or tuple of integers by a :class:`Series` incorrectly raising (:issue:`44674`)
- Bug in :meth:`DataFrame.rank` raising ``ValueError`` with ``object`` columns and ``method="first"`` (:issue:`41931`)
- Bug in :meth:`DataFrame.rank` treating missing values and extreme values as equal (for example ``np.nan`` and ``np.inf``), causing incorrect results when ``na_option="bottom"`` or ``na_option="top`` used (:issue:`41931`)
- Bug in ``numexpr`` engine still being used when the option ``compute.use_numexpr`` is set to ``False`` (:issue:`32556`)
Expand Down
16 changes: 10 additions & 6 deletions pandas/core/ops/array_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _masked_arith_op(x: np.ndarray, y, op):
return result


def _na_arithmetic_op(left, right, op, is_cmp: bool = False):
def _na_arithmetic_op(left: np.ndarray, right, op, is_cmp: bool = False):
"""
Return the result of evaluating op on the passed in values.

Expand All @@ -146,6 +146,7 @@ def _na_arithmetic_op(left, right, op, is_cmp: bool = False):
----------
left : np.ndarray
right : np.ndarray or scalar
Excludes DataFrame, Series, Index, ExtensionArray.
is_cmp : bool, default False
If this a comparison operation.

Expand All @@ -166,7 +167,7 @@ def _na_arithmetic_op(left, right, op, is_cmp: bool = False):
try:
result = func(left, right)
except TypeError:
if is_object_dtype(left) or is_object_dtype(right) and not is_cmp:
if not is_cmp and (is_object_dtype(left.dtype) or is_object_dtype(right)):
# For object dtype, fallback to a masked operation (only operating
# on the non-missing values)
# Don't do this for comparisons, as that will handle complex numbers
Expand All @@ -178,6 +179,7 @@ def _na_arithmetic_op(left, right, op, is_cmp: bool = False):
if is_cmp and (is_scalar(result) or result is NotImplemented):
# numpy returned a scalar instead of operating element-wise
# e.g. numeric array vs str
# TODO: can remove this after dropping some future numpy version?
return invalid_comparison(left, right, op)

return missing.dispatch_fill_zeros(op, left, right, result)
Expand Down Expand Up @@ -251,7 +253,8 @@ def comparison_op(left: ArrayLike, right: Any, op) -> ArrayLike:

rvalues = lib.item_from_zerodim(rvalues)
if isinstance(rvalues, list):
# TODO: same for tuples?
# We don't catch tuple here bc we may be comparing e.g. MultiIndex
# to a tuple that represents a single entry, see test_compare_tuple_strs
rvalues = np.asarray(rvalues)

if isinstance(rvalues, (np.ndarray, ABCExtensionArray)):
Expand All @@ -270,7 +273,7 @@ def comparison_op(left: ArrayLike, right: Any, op) -> ArrayLike:
# Call the method on lvalues
res_values = op(lvalues, rvalues)

elif is_scalar(rvalues) and isna(rvalues):
elif is_scalar(rvalues) and isna(rvalues): # TODO: but not pd.NA?
# numpy does not like comparisons vs None
if op is operator.ne:
res_values = np.ones(lvalues.shape, dtype=bool)
Expand Down Expand Up @@ -412,12 +415,13 @@ def get_array_op(op):
"""
if isinstance(op, partial):
# We get here via dispatch_to_series in DataFrame case
# TODO: avoid getting here
# e.g. test_rolling_consistency_var_debiasing_factors
return op

op_name = op.__name__.strip("_").lstrip("r")
if op_name == "arith_op":
# Reached via DataFrame._combine_frame
# Reached via DataFrame._combine_frame i.e. flex methods
# e.g. test_df_add_flex_filled_mixed_dtypes
return op

if op_name in {"eq", "ne", "lt", "le", "gt", "ge"}:
Expand Down
10 changes: 5 additions & 5 deletions pandas/core/ops/missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ def mask_zero_div_zero(x, y, result: np.ndarray) -> np.ndarray:
array([ inf, nan, -inf])
"""

if is_scalar(y):
if not hasattr(y, "dtype"):
# e.g. scalar, tuple
y = np.array(y)
if not hasattr(x, "dtype"):
# e.g scalar, tuple
x = np.array(x)

zmask = y == 0

if isinstance(zmask, bool):
# FIXME: numpy did not evaluate pointwise, seen in docs build
return result

if zmask.any():

# Flip sign if necessary for -0.0
Expand Down
7 changes: 0 additions & 7 deletions pandas/tests/series/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,13 +729,6 @@ def test_series_ops_name_retention(
# GH#33930 consistent name renteiton
op = all_binary_operators

if op is ops.rfloordiv and box in [list, tuple] and not flex:
request.node.add_marker(
pytest.mark.xfail(
reason="op fails because of inconsistent ndarray-wrapping GH#28759"
)
)

left = Series(range(10), name=names[0])
right = Series(range(10), name=names[1])

Expand Down