Skip to content

REGR: fix op(frame, frame2) with reindex #31679

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 9 commits into from
Feb 19, 2020
15 changes: 15 additions & 0 deletions pandas/core/ops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,13 +722,28 @@ def _arith_method_FRAME(cls, op, special):
@Appender(doc)
def f(self, other, axis=default_axis, level=None, fill_value=None):

orig_self, orig_other = self, other
self, other = _align_method_FRAME(self, other, axis, flex=True, level=level)

if isinstance(other, ABCDataFrame):
# Another DataFrame
pass_op = op if should_series_dispatch(self, other, op) else na_op
pass_op = pass_op if not is_logical else op

if isinstance(orig_other, ABCDataFrame):
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this be handled in .align? why is this needed at all?

if fill_value is None and level is None and axis is default_axis:
# TODO: any other cases we should handle here?
cols = orig_self.columns.intersection(orig_other.columns)
if not (
cols.equals(orig_self.columns)
and cols.equals(orig_other.columns)
):
# GH#31623, only operate on shared columns
new_left = orig_self[cols]
new_right = orig_other[cols]
result = op(new_left, new_right)
return result.reindex(self.columns, axis=1)

new_data = self._combine_frame(other, pass_op, fill_value)
return self._construct_result(new_data)

Expand Down
19 changes: 19 additions & 0 deletions pandas/tests/frame/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,25 @@ def test_operations_with_interval_categories_index(self, all_arithmetic_operator
expected = pd.DataFrame([[getattr(n, op)(num) for n in data]], columns=ind)
tm.assert_frame_equal(result, expected)

def test_frame_with_frame_reindex(self):
# GH#31623
df = pd.DataFrame(
{
"foo": [pd.Timestamp("2019"), pd.Timestamp("2020")],
"bar": [pd.Timestamp("2018"), pd.Timestamp("2021")],
},
columns=["foo", "bar"],
)
df2 = df[["foo"]]

result = df - df2

expected = pd.DataFrame(
{"foo": [pd.Timedelta(0), pd.Timedelta(0)], "bar": [np.nan, np.nan]},
columns=["bar", "foo"],
)
tm.assert_frame_equal(result, expected)


def test_frame_with_zero_len_series_corner_cases():
# GH#28600
Expand Down