Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 5 additions & 3 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -5341,7 +5341,7 @@ def reorder_levels(self, order, axis=0) -> "DataFrame":
# ----------------------------------------------------------------------
# Arithmetic / combination related

def _combine_frame(self, other, func, fill_value=None, level=None):
def _combine_frame(self, other: "DataFrame", func, fill_value=None):
# at this point we have `self._indexed_same(other)`

if fill_value is None:
Expand All @@ -5368,16 +5368,18 @@ def _arith_op(left, right):

return new_data

def _combine_match_index(self, other, func):
def _combine_match_index(self, other: Series, func):
# at this point we have `self.index.equals(other.index)`

if ops.should_series_dispatch(self, other, func):
# operate column-wise; avoid costly object-casting in `.values`
new_data = ops.dispatch_to_series(self, other, func)
else:
# fastpath --> operate directly on values
other_vals = other.values.reshape(-1, 1)
with np.errstate(all="ignore"):
new_data = func(self.values.T, other.values).T
new_data = func(self.values, other_vals)
new_data = dispatch_fill_zeros(func, self.values, other_vals, new_data)
return new_data

def _construct_result(self, result) -> "DataFrame":
Expand Down
17 changes: 7 additions & 10 deletions pandas/core/ops/missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,26 +109,23 @@ def mask_zero_div_zero(x, y, result):
return result

if zmask.any():
shape = result.shape

# Flip sign if necessary for -0.0
zneg_mask = zmask & np.signbit(y)
zpos_mask = zmask & ~zneg_mask

nan_mask = (zmask & (x == 0)).ravel()
nan_mask = zmask & (x == 0)
with np.errstate(invalid="ignore"):
neginf_mask = ((zpos_mask & (x < 0)) | (zneg_mask & (x > 0))).ravel()
posinf_mask = ((zpos_mask & (x > 0)) | (zneg_mask & (x < 0))).ravel()
neginf_mask = (zpos_mask & (x < 0)) | (zneg_mask & (x > 0))
posinf_mask = (zpos_mask & (x > 0)) | (zneg_mask & (x < 0))

if nan_mask.any() or neginf_mask.any() or posinf_mask.any():
# Fill negative/0 with -inf, positive/0 with +inf, 0/0 with NaN
result = result.astype("float64", copy=False).ravel()

np.putmask(result, nan_mask, np.nan)
np.putmask(result, posinf_mask, np.inf)
np.putmask(result, neginf_mask, -np.inf)
result = result.astype("float64", copy=False)

result = result.reshape(shape)
result[nan_mask] = np.nan
result[posinf_mask] = np.inf
result[neginf_mask] = -np.inf

return result

Expand Down
15 changes: 15 additions & 0 deletions pandas/tests/frame/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,21 @@ def test_df_flex_cmp_constant_return_types_empty(self, opname):


class TestFrameFlexArithmetic:
def test_floordiv_axis0(self):
# make sure we df.floordiv(ser, axis=0) matches column-wise result
arr = np.arange(3)
ser = pd.Series(arr)
df = pd.DataFrame({"A": ser, "B": ser})

result = df.floordiv(ser, axis=0)

expected = pd.DataFrame({col: df[col] // ser for col in df.columns})

tm.assert_frame_equal(result, expected)

result2 = df.floordiv(ser.values, axis=0)
tm.assert_frame_equal(result2, expected)

def test_df_add_td64_columnwise(self):
# GH 22534 Check that column-wise addition broadcasts correctly
dti = pd.date_range("2016-01-01", periods=10)
Expand Down