Skip to content

Commit 3e6bed7

Browse files
committed
deprecate alignment arithmetic between Series with non-aligned MultiIndexeså
1 parent 1fd184d commit 3e6bed7

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,7 @@ Other Deprecations
854854
- Deprecated backward-compatibility behavior for :meth:`DataFrame.select_dtypes` matching ``str`` dtype when ``np.object_`` is specified (:issue:`61916`)
855855
- Deprecated option ``future.no_silent_downcasting``, as it is no longer used. In a future version accessing this option will raise (:issue:`59502`)
856856
- Deprecated passing non-Index types to :meth:`Index.join`; explicitly convert to Index first (:issue:`62897`)
857+
- Deprecated silent alignment on arithmetic operations between :class:`Series` with non-aligned ``MultiIndexes`` (:issue:`25891`)
857858
- Deprecated silent casting of non-datetime ``other`` to datetime in :meth:`Series.combine_first` (:issue:`62931`)
858859
- Deprecated silently casting strings to :class:`Timedelta` in binary operations with :class:`Timedelta` (:issue:`59653`)
859860
- Deprecated slicing on a :class:`Series` or :class:`DataFrame` with a :class:`DatetimeIndex` using a ``datetime.date`` object, explicitly cast to :class:`Timestamp` instead (:issue:`35830`)

pandas/core/series.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6662,6 +6662,20 @@ def _logical_method(self, other, op):
66626662
return self._construct_result(res_values, name=res_name, other=other)
66636663

66646664
def _arith_method(self, other, op):
6665+
if (
6666+
isinstance(self.index, MultiIndex)
6667+
and isinstance(other.index, MultiIndex)
6668+
and self.index.names != other.index.names
6669+
):
6670+
# GH#25891
6671+
warnings.warn(
6672+
"The silent alignment on arithmetic operations between "
6673+
"'Series' with non-aligned MultiIndexes will be removed "
6674+
"in a future version, please use aligned MultiIndexes.",
6675+
Pandas4Warning,
6676+
stacklevel=find_stack_level(),
6677+
)
6678+
66656679
self, other = self._align_for_op(other)
66666680
return base.IndexOpsMixin._arith_method(self, other, op)
66676681

pandas/tests/series/test_arithmetic.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import pytest
1515

1616
from pandas._libs import lib
17+
from pandas.errors import Pandas4Warning
1718

1819
import pandas as pd
1920
from pandas import (
@@ -1043,14 +1044,19 @@ def test_series_varied_multiindex_alignment():
10431044
[1000 * i for i in range(1, 5)],
10441045
index=pd.MultiIndex.from_product([list("xy"), [1, 2]], names=["xy", "num"]),
10451046
)
1046-
result = s1.loc[pd.IndexSlice[["a"], :, :]] + s2
1047+
msg = (
1048+
"The silent alignment on arithmetic operations between "
1049+
"'Series' with non-aligned MultiIndexes"
1050+
)
10471051
expected = Series(
10481052
[1000, 2001, 3002, 4003],
10491053
index=pd.MultiIndex.from_tuples(
10501054
[("a", "x", 1), ("a", "x", 2), ("a", "y", 1), ("a", "y", 2)],
10511055
names=["ab", "xy", "num"],
10521056
),
10531057
)
1058+
with tm.assert_produces_warning(Pandas4Warning, match=msg):
1059+
result = s1.loc[pd.IndexSlice[["a"], :, :]] + s2
10541060
tm.assert_series_equal(result, expected)
10551061

10561062

@@ -1060,3 +1066,36 @@ def test_rmod_consistent_large_series():
10601066
expected = Series([1] * 10001)
10611067

10621068
tm.assert_series_equal(result, expected)
1069+
1070+
1071+
def test_alignment_on_arithmetic_with_nonaligned_multiindex_deprecated(
1072+
all_arithmetic_operators,
1073+
):
1074+
# GH#25891
1075+
index1 = pd.MultiIndex.from_product([[], []], names=["T", "N"])
1076+
s1 = Series(index=index1)
1077+
s1["T.1A", "N.0"] = 0.5
1078+
s1["T.1B", "N.0"] = 0.5
1079+
op = tm.get_op_from_name(all_arithmetic_operators)
1080+
1081+
index2 = pd.MultiIndex.from_product([[], []], names=["N", "M"])
1082+
s2 = Series(index=index2)
1083+
s2["N.0", "M.0"] = 0.5
1084+
1085+
expected = Series(
1086+
[0.25, 0.25],
1087+
index=pd.MultiIndex.from_tuples(
1088+
[("T.1A", "N.0", "M.0"), ("T.1B", "N.0", "M.0")],
1089+
names=["T", "N", "M"],
1090+
),
1091+
)
1092+
msg = (
1093+
"The silent alignment on arithmetic operations between "
1094+
"'Series' with non-aligned MultiIndexes"
1095+
)
1096+
with tm.assert_produces_warning(Pandas4Warning, match=msg):
1097+
result = s1 * s2
1098+
tm.assert_series_equal(result, expected)
1099+
1100+
with tm.assert_produces_warning(Pandas4Warning, match=msg):
1101+
op(s1, s2)

0 commit comments

Comments
 (0)