Skip to content

Commit 4e617e6

Browse files
committed
Fix fill value, closes pandas-dev#26987
1 parent 2efb607 commit 4e617e6

File tree

4 files changed

+78
-11
lines changed

4 files changed

+78
-11
lines changed

pandas/core/missing.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ def dispatch_missing(op, left, right, result):
702702
result : ndarray
703703
"""
704704
opstr = "__{opname}__".format(opname=op.__name__).replace("____", "__")
705-
if op in [operator.truediv, operator.floordiv, getattr(operator, "div", None)]:
705+
if op in [operator.truediv, operator.floordiv]:
706706
result = mask_zero_div_zero(left, right, result)
707707
elif op is operator.mod:
708708
result = fill_zeros(result, left, right, opstr, np.nan)
@@ -713,6 +713,29 @@ def dispatch_missing(op, left, right, result):
713713
return result
714714

715715

716+
# FIXME: de-duplicate with dispatch_missing
717+
def dispatch_fill_zeros(op, left, right, result, fill_value):
718+
"""
719+
Call fill_zeros with the appropriate fill value depending on the operation,
720+
with special logic for divmod and rdivmod.
721+
"""
722+
from pandas.core.ops import rdivmod
723+
724+
if op is divmod:
725+
result = (
726+
fill_zeros(result[0], left, right, "__floordiv__", np.inf),
727+
fill_zeros(result[1], left, right, "__mod__", np.nan),
728+
)
729+
elif op is rdivmod:
730+
result = (
731+
fill_zeros(result[0], left, right, "__rfloordiv__", np.inf),
732+
fill_zeros(result[1], left, right, "__rmod__", np.nan),
733+
)
734+
else:
735+
result = fill_zeros(result, left, right, op.__name__, fill_value)
736+
return result
737+
738+
716739
def _interp_limit(invalid, fw_limit, bw_limit):
717740
"""
718741
Get indexers of values that won't be filled

pandas/core/ops.py

+2-9
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ def _gen_fill_zeros(name):
295295
"""
296296
name = name.strip("__")
297297
if "div" in name:
298-
# truediv, floordiv, div, and reversed variants
298+
# truediv, floordiv, and reversed variants
299299
fill_value = np.inf
300300
elif "mod" in name:
301301
# mod, rmod
@@ -1718,14 +1718,7 @@ def na_op(x, y):
17181718
return libalgos.arrmap_object(x, lambda val: op(val, y))
17191719
raise
17201720

1721-
if isinstance(result, tuple):
1722-
# e.g. divmod
1723-
result = tuple(
1724-
missing.fill_zeros(r, x, y, op_name, fill_zeros) for r in result
1725-
)
1726-
else:
1727-
result = missing.fill_zeros(result, x, y, op_name, fill_zeros)
1728-
return result
1721+
return missing.dispatch_fill_zeros(op, x, y, result, fill_zeros)
17291722

17301723
def wrapper(left, right):
17311724
if isinstance(right, ABCDataFrame):

pandas/tests/arithmetic/test_numeric.py

+51-1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,54 @@ def test_ser_div_ser(self, dtype1, dtype2):
299299
tm.assert_series_equal(result, expected)
300300
assert not result.equals(second / first)
301301

302+
@pytest.mark.parametrize(
303+
"dtype2",
304+
[
305+
np.int64,
306+
np.int32,
307+
np.int16,
308+
np.int8,
309+
np.float64,
310+
np.float32,
311+
np.float16,
312+
np.uint64,
313+
np.uint32,
314+
np.uint16,
315+
np.uint8,
316+
],
317+
)
318+
@pytest.mark.parametrize("dtype1", [np.int64, np.float64, np.uint64])
319+
def test_ser_divmod_zero(self, dtype1, dtype2):
320+
# GH#26987
321+
left = pd.Series([1, 1]).astype(dtype1)
322+
right = pd.Series([0, 2]).astype(dtype2)
323+
324+
expected = left // right, left % right
325+
result = divmod(left, right)
326+
327+
tm.assert_series_equal(result[0], expected[0])
328+
tm.assert_series_equal(result[1], expected[1])
329+
330+
# rdivmod case
331+
result = divmod(left.values, right)
332+
tm.assert_series_equal(result[0], expected[0])
333+
tm.assert_series_equal(result[1], expected[1])
334+
335+
def test_ser_divmod_inf(self):
336+
left = pd.Series([np.inf, 1.0])
337+
right = pd.Series([np.inf, 2.0])
338+
339+
expected = left // right, left % right
340+
result = divmod(left, right)
341+
342+
tm.assert_series_equal(result[0], expected[0])
343+
tm.assert_series_equal(result[1], expected[1])
344+
345+
# rdivmod case
346+
result = divmod(left.values, right)
347+
tm.assert_series_equal(result[0], expected[0])
348+
tm.assert_series_equal(result[1], expected[1])
349+
302350
def test_rdiv_zero_compat(self):
303351
# GH#8674
304352
zero_array = np.array([0] * 5)
@@ -662,7 +710,9 @@ def test_modulo2(self):
662710
result2 = p["second"] % p["first"]
663711
assert not result.equals(result2)
664712

665-
# GH#9144
713+
def test_modulo_zero_int(self):
714+
# GH#9144
715+
with np.errstate(all="ignore"):
666716
s = Series([0, 1])
667717

668718
result = s % 0

pandas/tests/sparse/series/test_series.py

+1
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ def check(a, b):
578578
_check_op(a, b, lambda x, y: operator.floordiv(y, x))
579579
_check_op(a, b, lambda x, y: operator.mul(y, x))
580580

581+
# FIXME: don't leave commented-out
581582
# NaN ** 0 = 1 in C?
582583
# _check_op(a, b, operator.pow)
583584
# _check_op(a, b, lambda x, y: operator.pow(y, x))

0 commit comments

Comments
 (0)