Skip to content

Commit 0308fe9

Browse files
committed
Merge pull request #6359 from jreback/int_div
BUG: correctly handle placement of pos/neg inf when dividing by integer 0)
2 parents 75a8d75 + 0713a0b commit 0308fe9

File tree

6 files changed

+40
-16
lines changed

6 files changed

+40
-16
lines changed

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ Bug Fixes
105105
- TimeGrouper has a more compatible API to the rest of the groupers (e.g. ``groups`` was missing) (:issue:`3881`)
106106
- Bug in ``pd.eval`` when parsing strings with possible tokens like ``'&'``
107107
(:issue:`6351`)
108+
- Bug correctly handle placements of ``-inf`` in Panels when dividing by integer 0 (:issue:`6359`)
108109

109110
pandas 0.13.1
110111
-------------

pandas/core/common.py

+24-4
Original file line numberDiff line numberDiff line change
@@ -1179,13 +1179,23 @@ def _lcd_dtypes(a_dtype, b_dtype):
11791179
return np.object
11801180

11811181

1182-
def _fill_zeros(result, y, fill):
1183-
""" if we have an integer value (or array in y)
1182+
def _fill_zeros(result, x, y, name, fill):
1183+
"""
1184+
if this is a reversed op, then flip x,y
1185+
1186+
if we have an integer value (or array in y)
11841187
and we have 0's, fill them with the fill,
11851188
return the result
1189+
1190+
mask the nan's from x
11861191
"""
11871192

11881193
if fill is not None:
1194+
1195+
if name.startswith('r'):
1196+
x,y = y,x
1197+
1198+
11891199
if not isinstance(y, np.ndarray):
11901200
dtype, value = _infer_dtype_from_scalar(y)
11911201
y = pa.empty(result.shape, dtype=dtype)
@@ -1196,8 +1206,18 @@ def _fill_zeros(result, y, fill):
11961206
mask = y.ravel() == 0
11971207
if mask.any():
11981208
shape = result.shape
1199-
result, changed = _maybe_upcast_putmask(
1200-
result.ravel(), mask, fill)
1209+
result = result.ravel().astype('float64')
1210+
1211+
signs = np.sign(result)
1212+
nans = np.isnan(x.ravel())
1213+
np.putmask(result, mask & ~nans, fill)
1214+
1215+
# if we have a fill of inf, then sign it
1216+
# correctly
1217+
# GH 6178
1218+
if np.isinf(fill):
1219+
np.putmask(result,signs<0 & mask & ~nans,-fill)
1220+
12011221
result = result.reshape(shape)
12021222

12031223
return result

pandas/core/ops.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ def na_op(x, y):
454454

455455
result, changed = com._maybe_upcast_putmask(result, -mask, pa.NA)
456456

457-
result = com._fill_zeros(result, y, fill_zeros)
457+
result = com._fill_zeros(result, x, y, name, fill_zeros)
458458
return result
459459

460460
def wrapper(left, right, name=name):
@@ -749,7 +749,7 @@ def na_op(x, y):
749749
result, changed = com._maybe_upcast_putmask(result, -mask, np.nan)
750750
result = result.reshape(x.shape)
751751

752-
result = com._fill_zeros(result, y, fill_zeros)
752+
result = com._fill_zeros(result, x, y, name, fill_zeros)
753753

754754
return result
755755

@@ -913,7 +913,7 @@ def na_op(x, y):
913913
result[mask] = op(x[mask], y)
914914
result, changed = com._maybe_upcast_putmask(result, -mask, pa.NA)
915915

916-
result = com._fill_zeros(result, y, fill_zeros)
916+
result = com._fill_zeros(result, x, y, name, fill_zeros)
917917
return result
918918

919919
# work only for scalars

pandas/core/panel.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1396,7 +1396,7 @@ def na_op(x, y):
13961396
# handles discrepancy between numpy and numexpr on division/mod
13971397
# by 0 though, given that these are generally (always?)
13981398
# non-scalars, I'm not sure whether it's worth it at the moment
1399-
result = com._fill_zeros(result, y, fill_zeros)
1399+
result = com._fill_zeros(result, x, y, name, fill_zeros)
14001400
return result
14011401

14021402
@Substitution(name)

pandas/tests/test_panel.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -2071,23 +2071,20 @@ def test_arith_flex_panel(self):
20712071
else:
20722072
aliases = {'div': 'truediv'}
20732073
self.panel = self.panel.to_panel()
2074-
n = np.random.randint(-50, 50)
2075-
for op in ops:
2076-
try:
2074+
2075+
for n in [ np.random.randint(-50, -1), np.random.randint(1, 50), 0]:
2076+
for op in ops:
20772077
alias = aliases.get(op, op)
20782078
f = getattr(operator, alias)
2079-
result = getattr(self.panel, op)(n)
20802079
exp = f(self.panel, n)
2080+
result = getattr(self.panel, op)(n)
20812081
assert_panel_equal(result, exp, check_panel_type=True)
20822082

20832083
# rops
20842084
r_f = lambda x, y: f(y, x)
2085-
result = getattr(self.panel, 'r' + op)(n)
20862085
exp = r_f(self.panel, n)
2086+
result = getattr(self.panel, 'r' + op)(n)
20872087
assert_panel_equal(result, exp)
2088-
except:
2089-
print("Failing operation %r" % op)
2090-
raise
20912088

20922089
def test_sort(self):
20932090
def is_sorted(arr):

pandas/tests/test_series.py

+6
Original file line numberDiff line numberDiff line change
@@ -2212,6 +2212,12 @@ def test_div(self):
22122212
assert_series_equal(result, p['first'].astype('float64'))
22132213
self.assertFalse(np.array_equal(result, p['second'] / p['first']))
22142214

2215+
# inf signing
2216+
s = Series([np.nan,1.,-1.])
2217+
result = s / 0
2218+
expected = Series([np.nan,np.inf,-np.inf])
2219+
assert_series_equal(result, expected)
2220+
22152221
def test_operators(self):
22162222

22172223
def _check_op(series, other, op, pos_only=False):

0 commit comments

Comments
 (0)