diff --git a/pandas/core/frame.py b/pandas/core/frame.py index bf9d1cd7d30b9..43b4e8c3cf007 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -842,12 +842,14 @@ def __contains__(self, key): sub = _arith_method(operator.sub, 'subtract', '-') div = divide = _arith_method(lambda x, y: x / y, 'divide', '/') pow = _arith_method(operator.pow, 'pow', '**') + mod = _arith_method(lambda x, y: x % y, 'mod') radd = _arith_method(_radd_compat, 'radd') rmul = _arith_method(operator.mul, 'rmultiply') rsub = _arith_method(lambda x, y: y - x, 'rsubtract') rdiv = _arith_method(lambda x, y: y / x, 'rdivide') rpow = _arith_method(lambda x, y: y ** x, 'rpow') + rmod = _arith_method(lambda x, y: y % x, 'rmod') __add__ = _arith_method(operator.add, '__add__', '+', default_axis=None) __sub__ = _arith_method(operator.sub, '__sub__', '-', default_axis=None) @@ -874,7 +876,8 @@ def __contains__(self, key): default_axis=None, fill_zeros=np.inf) __rpow__ = _arith_method(lambda x, y: y ** x, '__rpow__', default_axis=None) - __rmod__ = _arith_method(operator.mod, '__rmod__', default_axis=None, fill_zeros=np.nan) + __rmod__ = _arith_method(lambda x, y: y % x, '__rmod__', default_axis=None, + fill_zeros=np.nan) # boolean operators __and__ = _arith_method(operator.and_, '__and__', '&') diff --git a/pandas/core/series.py b/pandas/core/series.py index 47ae56f6ca2fd..bd76d91629121 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1266,7 +1266,7 @@ def iteritems(self): __rtruediv__ = _arith_method(lambda x, y: y / x, '__truediv__', fill_zeros=np.inf) __rfloordiv__ = _arith_method(lambda x, y: y // x, '__floordiv__', fill_zeros=np.inf) __rpow__ = _arith_method(lambda x, y: y ** x, '__pow__') - __rmod__ = _arith_method(operator.mod, '__mod__', fill_zeros=np.nan) + __rmod__ = _arith_method(lambda x, y: y % x, '__mod__', fill_zeros=np.nan) # comparisons __gt__ = _comp_method(operator.gt, '__gt__') @@ -2127,6 +2127,7 @@ def _binop(self, other, func, level=None, fill_value=None): except AttributeError: # pragma: no cover # Python 3 div = _flex_method(operator.truediv, 'divide') + mod = _flex_method(operator.mod, 'mod') def combine(self, other, func, fill_value=nan): """ diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index ef4791aa0968c..7b2ab32a51ecc 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -4041,6 +4041,13 @@ def test_modulo(self): result2 = DataFrame(p.values.astype('float64') % 0,index=p.index,columns=p.columns) assert_frame_equal(result2,expected) + # not commutative with series + p = DataFrame(np.random.randn(10, 5)) + s = p[0] + res = s % p + res2 = p % s + self.assertFalse(np.array_equal(res.fillna(0), res2.fillna(0))) + def test_div(self): # integer div, but deal with the 0's @@ -4062,6 +4069,12 @@ def test_div(self): result2 = DataFrame(p.values.astype('float64')/0,index=p.index,columns=p.columns).fillna(np.inf) assert_frame_equal(result2,expected) + p = DataFrame(np.random.randn(10, 5)) + s = p[0] + res = s / p + res2 = p / s + self.assertFalse(np.array_equal(res.fillna(0), res2.fillna(0))) + def test_logical_operators(self): import operator @@ -4391,11 +4404,13 @@ def test_arith_flex_series(self): assert_frame_equal(df.sub(row), df - row) assert_frame_equal(df.div(row), df / row) assert_frame_equal(df.mul(row), df * row) + assert_frame_equal(df.mod(row), df % row) assert_frame_equal(df.add(col, axis=0), (df.T + col).T) assert_frame_equal(df.sub(col, axis=0), (df.T - col).T) assert_frame_equal(df.div(col, axis=0), (df.T / col).T) assert_frame_equal(df.mul(col, axis=0), (df.T * col).T) + assert_frame_equal(df.mod(col, axis=0), (df.T % col).T) def test_arith_non_pandas_object(self): df = self.simple diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 05b5876f6fc86..09f3cc7b61f33 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -1737,6 +1737,11 @@ def test_modulo(self): expected = Series(p['first'].values % p['second'].values) assert_series_equal(result,expected) + p = p.astype('float64') + result = p['first'] % p['second'] + result2 = p['second'] % p['first'] + self.assertFalse(np.array_equal(result,result2)) + def test_div(self): # integer div, but deal with the 0's @@ -1761,6 +1766,7 @@ def test_div(self): assert_series_equal(result,p['first'].astype('float64')) else: assert_series_equal(result,p['first']) + self.assertFalse(np.array_equal(result, p['second'] / p['first'])) def test_operators(self): @@ -1773,7 +1779,7 @@ def _check_op(series, other, op, pos_only=False): tm.assert_almost_equal(cython_or_numpy, python) def check(series, other): - simple_ops = ['add', 'sub', 'mul', 'truediv', 'floordiv'] + simple_ops = ['add', 'sub', 'mul', 'truediv', 'floordiv', 'mod'] for opname in simple_ops: _check_op(series, other, getattr(operator, opname)) @@ -1787,6 +1793,7 @@ def check(series, other): _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(self.ts, self.ts * 2) check(self.ts, self.ts * 0)