-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
BUG: Consistent division by zero behavior for Index/Series #27321
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
Changes from 23 commits
6bd4fb1
d9943be
eb8b6d7
3edebac
eb60fc3
3cf8b1e
c34a9cc
158b003
b59b81a
f085d6b
339ed84
f03bd93
cd2f564
e362a08
7c6e127
97611c3
c30b40c
1ed12b8
45ffbc2
591eaaa
2841be0
518e2e9
2580048
f440c59
188ac99
6b411c4
77c2383
7b8880c
14010c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -332,6 +332,9 @@ def test_ser_divmod_zero(self, dtype1, any_real_dtype): | |
right = pd.Series([0, 2]).astype(dtype2) | ||
|
||
expected = left // right, left % right | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in future PR can you give some comments on what you ar doing here (filling np.inf on the integer divide) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
expected = list(expected) | ||
expected[0] = expected[0].astype(np.float64) | ||
expected[0][0] = np.inf | ||
result = divmod(left, right) | ||
|
||
tm.assert_series_equal(result[0], expected[0]) | ||
|
@@ -881,17 +884,16 @@ def check(series, other): | |
|
||
_check_op(series, other, operator.pow, pos_only=True) | ||
|
||
_check_op(series, other, lambda x, y: operator.add(y, x)) | ||
_check_op(series, other, lambda x, y: operator.sub(y, x)) | ||
_check_op(series, other, lambda x, y: operator.truediv(y, x)) | ||
_check_op(series, other, lambda x, y: operator.floordiv(y, x)) | ||
_check_op(series, other, lambda x, y: operator.mul(y, x)) | ||
_check_op(series, other, lambda x, y: operator.pow(y, x), pos_only=True) | ||
_check_op(series, other, lambda x, y: operator.mod(y, x)) | ||
_check_op(series, other, ops.radd) | ||
_check_op(series, other, ops.rsub) | ||
_check_op(series, other, ops.rtruediv) | ||
_check_op(series, other, ops.rfloordiv) | ||
_check_op(series, other, ops.rmul) | ||
_check_op(series, other, ops.rpow, pos_only=True) | ||
_check_op(series, other, ops.rmod) | ||
|
||
tser = tm.makeTimeSeries().rename("ts") | ||
check(tser, tser * 2) | ||
check(tser, tser * 0) | ||
check(tser, tser[::2]) | ||
check(tser, 5) | ||
|
||
|
@@ -931,13 +933,9 @@ def check(series, other): | |
|
||
tser = tm.makeTimeSeries().rename("ts") | ||
check(tser, tser * 2) | ||
check(tser, tser * 0) | ||
check(tser, tser[::2]) | ||
check(tser, 5) | ||
|
||
@pytest.mark.xfail( | ||
reason="Series division does not yet fill 1/0 consistently; Index does." | ||
) | ||
def test_series_divmod_zero(self): | ||
# Check that divmod uses pandas convention for division by zero, | ||
# which does not match numpy. | ||
|
@@ -950,8 +948,8 @@ def test_series_divmod_zero(self): | |
other = tser * 0 | ||
|
||
result = divmod(tser, other) | ||
exp1 = pd.Series([np.inf] * len(tser), index=tser.index) | ||
exp2 = pd.Series([np.nan] * len(tser), index=tser.index) | ||
exp1 = pd.Series([np.inf] * len(tser), index=tser.index, name="ts") | ||
exp2 = pd.Series([np.nan] * len(tser), index=tser.index, name="ts") | ||
tm.assert_series_equal(result[0], exp1) | ||
tm.assert_series_equal(result[1], exp2) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import operator | ||
from types import LambdaType | ||
|
||
import numpy as np | ||
from numpy import nan | ||
|
@@ -9,6 +10,7 @@ | |
|
||
import pandas as pd | ||
from pandas import DataFrame, Series, bdate_range, compat | ||
from pandas.core import ops | ||
from pandas.core.indexes.datetimes import DatetimeIndex | ||
from pandas.core.sparse import frame as spf | ||
from pandas.core.sparse.api import ( | ||
|
@@ -136,6 +138,12 @@ def test_constructor(self, float_frame, float_frame_int_kind, float_frame_fill0) | |
|
||
repr(float_frame) | ||
|
||
def test_constructor_fill_value_scalar(self): | ||
d = {"b": [2, 3], "a": [0, 1]} | ||
fill_value = np.array(np.nan) | ||
with pytest.raises(ValueError, match="must be a scalar"): | ||
SparseDataFrame(data=d, default_fill_value=fill_value) | ||
|
||
def test_constructor_dict_order(self): | ||
# GH19018 | ||
# initialization ordering: by insertion order if python>= 3.6, else | ||
|
@@ -418,6 +426,11 @@ def _compare_to_dense(a, b, da, db, op): | |
sparse_result = op(a, b) | ||
dense_result = op(da, db) | ||
|
||
if op in [operator.floordiv, ops.rfloordiv] or isinstance(op, LambdaType): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this not just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we don't want e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. k can you add that as a comment (future PR ok), as its not obvious There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
# Series sets 1//0 to np.inf, which SparseArray does not do (yet) | ||
mask = np.isinf(dense_result) & ~np.isinf(sparse_result.to_dense()) | ||
dense_result[mask] = np.nan | ||
|
||
fill = sparse_result.default_fill_value | ||
dense_result = dense_result.to_sparse(fill_value=fill) | ||
tm.assert_sp_frame_equal(sparse_result, dense_result, exact_indices=False) | ||
|
@@ -430,7 +443,6 @@ def _compare_to_dense(a, b, da, db, op): | |
) | ||
|
||
opnames = ["add", "sub", "mul", "truediv", "floordiv"] | ||
ops = [getattr(operator, name) for name in opnames] | ||
|
||
fidx = frame.index | ||
|
||
|
@@ -460,6 +472,7 @@ def _compare_to_dense(a, b, da, db, op): | |
f = lambda a, b: getattr(a, op)(b, axis="index") | ||
_compare_to_dense(frame, s, frame.to_dense(), s.to_dense(), f) | ||
|
||
# FIXME: dont leave commented-out | ||
# rops are not implemented | ||
# _compare_to_dense(s, frame, s.to_dense(), | ||
# frame.to_dense(), f) | ||
|
@@ -473,13 +486,14 @@ def _compare_to_dense(a, b, da, db, op): | |
frame.xs(fidx[5])[:2], | ||
] | ||
|
||
for op in ops: | ||
for name in opnames: | ||
op = getattr(operator, name) | ||
for s in series: | ||
_compare_to_dense(frame, s, frame.to_dense(), s, op) | ||
_compare_to_dense(s, frame, s, frame.to_dense(), op) | ||
|
||
# it works! | ||
result = frame + frame.loc[:, ["A", "B"]] # noqa | ||
frame + frame.loc[:, ["A", "B"]] | ||
|
||
def test_op_corners(self, float_frame, empty_frame): | ||
empty = empty_frame + empty_frame | ||
|
Uh oh!
There was an error while loading. Please reload this page.