Skip to content
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/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ Other API changes
an empty ``RangeIndex`` or empty ``Index`` with object dtype when determining
the dtype of the resulting Index (:issue:`60797`)
- :class:`IncompatibleFrequency` now subclasses ``TypeError`` instead of ``ValueError``. As a result, joins with mismatched frequencies now cast to object like other non-comparable joins, and arithmetic with indexes with mismatched frequencies align (:issue:`55782`)
- :class:`Series` "flex" methods like :meth:`Series.add` no longer allow passing a :class:`DataFrame` for ``other``; use the DataFrame reversed method instead (:issue:`46179`)
- :meth:`CategoricalIndex.append` no longer attempts to cast different-dtype indexes to the caller's dtype (:issue:`41626`)
- :meth:`ExtensionDtype.construct_array_type` is now a regular method instead of a ``classmethod`` (:issue:`58663`)
- Comparison operations between :class:`Index` and :class:`Series` now consistently return :class:`Series` regardless of which object is on the left or right (:issue:`36759`)
Expand Down
6 changes: 6 additions & 0 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -6069,6 +6069,12 @@ def _flex_method(self, other, op, *, level=None, fill_value=None, axis: Axis = 0
result = self._binop(other, op, level=level, fill_value=fill_value)
result._name = res_name
return result
elif isinstance(other, ABCDataFrame):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually last minute thought, would be worth still allowing this if the axis are already aligned?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so just revert and let non-aligned cases raises like before? maybe try to give a better message?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or if ser.flex_op(df, axis=0) gives a sensible result when ser.index.equals(df.index), just have a follow up PR to amend and not ser.index.equals(df.index) to this elif. I suppose it would be good to also have a test case for ser.flex_op(df, axis=0) when the indexes are aligned

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think "DataFrame is not allowed" is significantly simpler to communicate than "DataFrame is not allowed except when aligned"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah definitely. We can keep this as is and reconsider if anyone seriously complains

# GH#46179
raise TypeError(
f"Series.{op.__name__.strip('_')} does not support a DataFrame "
f"`other`. Use df.{op.__name__.strip('_')}(ser) instead."
)
else:
if fill_value is not None:
if isna(other):
Expand Down
18 changes: 18 additions & 0 deletions pandas/tests/series/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ def _check_fill(meth, op, a, b, fill_value=0):
# should accept axis=0 or axis='rows'
op(a, b, axis=0)

def test_flex_disallows_dataframe(self):
# GH#46179
df = pd.DataFrame(
{2010: [1], 2020: [3]},
index=pd.MultiIndex.from_product([["a"], ["b"]], names=["scen", "mod"]),
)

ser = Series(
[10.0, 20.0, 30.0],
index=pd.MultiIndex.from_product(
[["a"], ["b"], [0, 1, 2]], names=["scen", "mod", "id"]
),
)

msg = "Series.add does not support a DataFrame `other`"
with pytest.raises(TypeError, match=msg):
ser.add(df, axis=0)


class TestSeriesArithmetic:
# Some of these may end up in tests/arithmetic, but are not yet sorted
Expand Down
Loading