Skip to content

ENH: DataFrame __divmod__, __rdivmod__ #37165

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
Oct 17, 2020
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.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ Other enhancements
- Added :meth:`Rolling.sem()` and :meth:`Expanding.sem()` to compute the standard error of mean (:issue:`26476`).
- :meth:`Rolling.var()` and :meth:`Rolling.std()` use Kahan summation and Welfords Method to avoid numerical issues (:issue:`37051`)
- :meth:`DataFrame.plot` now recognizes ``xlabel`` and ``ylabel`` arguments for plots of type ``scatter`` and ``hexbin`` (:issue:`37001`)
- :class:`DataFrame` now supports ``divmod`` operation (:issue:`37165`)

.. _whatsnew_120.api_breaking.python:

Expand Down
12 changes: 12 additions & 0 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -5957,6 +5957,18 @@ def _construct_result(self, result) -> DataFrame:
out.index = self.index
return out

def __divmod__(self, other) -> Tuple[DataFrame, DataFrame]:
# Naive implementation, room for optimization
div = self // other
mod = self - div * other
return div, mod

def __rdivmod__(self, other) -> Tuple[DataFrame, DataFrame]:
# Naive implementation, room for optimization
div = other // self
mod = other - div * self
return div, mod

# ----------------------------------------------------------------------
# Combination-Related

Expand Down
15 changes: 6 additions & 9 deletions pandas/tests/arithmetic/test_timedelta64.py
Original file line number Diff line number Diff line change
Expand Up @@ -1900,10 +1900,13 @@ def test_td64arr_mod_tdscalar(self, box_with_array, three_days):
result = tdarr % three_days
tm.assert_equal(result, expected)

if box_with_array is pd.DataFrame:
pytest.xfail("DataFrame does not have __divmod__ or __rdivmod__")
warn = None
if box_with_array is pd.DataFrame and isinstance(three_days, pd.DateOffset):
warn = PerformanceWarning

with tm.assert_produces_warning(warn):
result = divmod(tdarr, three_days)

result = divmod(tdarr, three_days)
tm.assert_equal(result[1], expected)
tm.assert_equal(result[0], tdarr // three_days)

Expand All @@ -1921,9 +1924,6 @@ def test_td64arr_mod_int(self, box_with_array):
with pytest.raises(TypeError, match=msg):
2 % tdarr

if box_with_array is pd.DataFrame:
pytest.xfail("DataFrame does not have __divmod__ or __rdivmod__")

result = divmod(tdarr, 2)
tm.assert_equal(result[1], expected)
tm.assert_equal(result[0], tdarr // 2)
Expand All @@ -1939,9 +1939,6 @@ def test_td64arr_rmod_tdscalar(self, box_with_array, three_days):
result = three_days % tdarr
tm.assert_equal(result, expected)

if box_with_array is pd.DataFrame:
pytest.xfail("DataFrame does not have __divmod__ or __rdivmod__")

result = divmod(three_days, tdarr)
tm.assert_equal(result[1], expected)
tm.assert_equal(result[0], three_days // tdarr)
Expand Down