From bb32564c3e1a9c40fb117d87c78073ac235d884f Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 11 Nov 2018 16:15:17 -0800 Subject: [PATCH] TST: Fix xfailing DataFrame arithmetic tests by transposing (#23620) --- pandas/tests/arithmetic/conftest.py | 23 ++-- pandas/tests/arithmetic/test_datetime64.py | 26 ++-- pandas/tests/arithmetic/test_period.py | 43 +++---- pandas/tests/arithmetic/test_timedelta64.py | 131 +++++++++----------- pandas/util/testing.py | 7 +- 5 files changed, 113 insertions(+), 117 deletions(-) diff --git a/pandas/tests/arithmetic/conftest.py b/pandas/tests/arithmetic/conftest.py index cf1abc6f79101..9ee5e05638978 100644 --- a/pandas/tests/arithmetic/conftest.py +++ b/pandas/tests/arithmetic/conftest.py @@ -158,19 +158,18 @@ def box_df_fail(request): return request.param -@pytest.fixture(params=[ - pd.Index, - pd.Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Tries to broadcast " - "incorrectly", - strict=True, raises=ValueError)) -], ids=lambda x: x.__name__) -def box_df_broadcast_failure(request): - """ - Fixture equivalent to `box` but with the common failing case where - the DataFrame operation tries to broadcast incorrectly. +@pytest.fixture(params=[(pd.Index, False), + (pd.Series, False), + (pd.DataFrame, False), + pytest.param((pd.DataFrame, True), + marks=pytest.mark.xfail(strict=True))], + ids=lambda x: x[0].__name__ + '-' + str(x[1])) +def box_transpose_fail(request): + """ + Fixture similar to `box` but testing both transpose cases for DataFrame, + with the tranpose=True case xfailed. """ + # GH#23620 return request.param diff --git a/pandas/tests/arithmetic/test_datetime64.py b/pandas/tests/arithmetic/test_datetime64.py index 73921a18ee5c7..b25e9a9a485c2 100644 --- a/pandas/tests/arithmetic/test_datetime64.py +++ b/pandas/tests/arithmetic/test_datetime64.py @@ -1155,14 +1155,18 @@ def test_dti_add_intarray_no_freq(self, box): def test_dti_add_timedeltalike(self, tz_naive_fixture, two_hours, box_with_datetime): # GH#22005, GH#22163 check DataFrame doesn't raise TypeError + box = box_with_datetime + tz = tz_naive_fixture rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz) - rng = tm.box_expected(rng, box_with_datetime) + + # FIXME: calling with transpose=True raises ValueError + rng = tm.box_expected(rng, box, transpose=False) result = rng + two_hours expected = pd.date_range('2000-01-01 02:00', '2000-02-01 02:00', tz=tz) - expected = tm.box_expected(expected, box_with_datetime) + expected = tm.box_expected(expected, box, transpose=False) tm.assert_equal(result, expected) def test_dti_iadd_timedeltalike(self, tz_naive_fixture, two_hours): @@ -1192,12 +1196,15 @@ def test_dti_isub_timedeltalike(self, tz_naive_fixture, two_hours): def test_dt64arr_add_sub_td64_nat(self, box, tz_naive_fixture): # GH#23320 special handling for timedelta64("NaT") tz = tz_naive_fixture + dti = pd.date_range("1994-04-01", periods=9, tz=tz, freq="QS") other = np.timedelta64("NaT") expected = pd.DatetimeIndex(["NaT"] * 9, tz=tz) - obj = tm.box_expected(dti, box) - expected = tm.box_expected(expected, box) + # FIXME: fails with transpose=True due to tz-aware DataFrame + # transpose bug + obj = tm.box_expected(dti, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = obj + other tm.assert_equal(result, expected) @@ -1450,10 +1457,8 @@ def test_sub_period(self, freq, box_with_datetime): operator.sub, ops.rsub]) @pytest.mark.parametrize('pi_freq', ['D', 'W', 'Q', 'H']) @pytest.mark.parametrize('dti_freq', [None, 'D']) - def test_dti_sub_pi(self, dti_freq, pi_freq, op, box_df_broadcast_failure): + def test_dti_sub_pi(self, dti_freq, pi_freq, op, box): # GH#20049 subtracting PeriodIndex should raise TypeError - box = box_df_broadcast_failure - dti = pd.DatetimeIndex(['2011-01-01', '2011-01-02'], freq=dti_freq) pi = dti.to_period(pi_freq) @@ -1782,6 +1787,8 @@ def test_dti_with_offset_series(self, tz_naive_fixture, names): def test_dti_add_offset_tzaware(self, tz_aware_fixture, box_with_datetime): # GH#21610, GH#22163 ensure DataFrame doesn't return object-dtype + box = box_with_datetime + timezone = tz_aware_fixture if timezone == 'US/Pacific': dates = date_range('2012-11-01', periods=3, tz=timezone) @@ -1793,8 +1800,9 @@ def test_dti_add_offset_tzaware(self, tz_aware_fixture, box_with_datetime): expected = DatetimeIndex(['2010-11-01 05:00', '2010-11-01 06:00', '2010-11-01 07:00'], freq='H', tz=timezone) - dates = tm.box_expected(dates, box_with_datetime) - expected = tm.box_expected(expected, box_with_datetime) + # FIXME: these raise ValueError with transpose=True + dates = tm.box_expected(dates, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) # TODO: parametrize over the scalar being added? radd? sub? offset = dates + pd.offsets.Hour(5) diff --git a/pandas/tests/arithmetic/test_period.py b/pandas/tests/arithmetic/test_period.py index 687d07082ea33..a26a11cb6be9e 100644 --- a/pandas/tests/arithmetic/test_period.py +++ b/pandas/tests/arithmetic/test_period.py @@ -70,9 +70,8 @@ def test_parr_cmp_period_scalar(self, freq, box): tm.assert_equal(per >= base, exp) @pytest.mark.parametrize('freq', ['M', '2M', '3M']) - def test_parr_cmp_pi(self, freq, box_df_fail): + def test_parr_cmp_pi(self, freq, box): # GH#13200 - box = box_df_fail xbox = np.ndarray if box is pd.Index else box base = PeriodIndex(['2011-01', '2011-02', '2011-03', '2011-04'], @@ -108,11 +107,9 @@ def test_parr_cmp_pi(self, freq, box_df_fail): tm.assert_equal(base <= idx, exp) @pytest.mark.parametrize('freq', ['M', '2M', '3M']) - def test_parr_cmp_pi_mismatched_freq_raises(self, freq, box_df_fail): + def test_parr_cmp_pi_mismatched_freq_raises(self, freq, box): # GH#13200 # different base freq - box = box_df_fail - base = PeriodIndex(['2011-01', '2011-02', '2011-03', '2011-04'], freq=freq) base = tm.box_expected(base, box) @@ -302,9 +299,7 @@ class TestPeriodIndexArithmetic(object): # PeriodIndex - other is defined for integers, timedelta-like others, # and PeriodIndex (with matching freq) - def test_parr_add_iadd_parr_raises(self, box_df_broadcast_failure): - box = box_df_broadcast_failure - + def test_parr_add_iadd_parr_raises(self, box): rng = pd.period_range('1/1/2000', freq='D', periods=5) other = pd.period_range('1/6/2000', freq='D', periods=5) # TODO: parametrize over boxes for other? @@ -346,9 +341,7 @@ def test_pi_sub_pi_with_nat(self): expected = pd.Index([pd.NaT, 0 * off, 0 * off, 0 * off, 0 * off]) tm.assert_index_equal(result, expected) - def test_parr_sub_pi_mismatched_freq(self, box_df_broadcast_failure): - box = box_df_broadcast_failure - + def test_parr_sub_pi_mismatched_freq(self, box): rng = pd.period_range('1/1/2000', freq='D', periods=5) other = pd.period_range('1/6/2000', freq='H', periods=5) # TODO: parametrize over boxes for other? @@ -364,9 +357,6 @@ def test_parr_sub_pi_mismatched_freq(self, box_df_broadcast_failure): @pytest.mark.parametrize('op', [operator.add, ops.radd, operator.sub, ops.rsub]) def test_pi_add_sub_float(self, op, other, box): - if box is pd.DataFrame and isinstance(other, np.ndarray): - pytest.xfail(reason="Tries to broadcast incorrectly") - dti = pd.DatetimeIndex(['2011-01-01', '2011-01-02'], freq='D') pi = dti.to_period('D') pi = tm.box_expected(pi, box) @@ -563,15 +553,18 @@ def test_pi_sub_isub_offset(self): rng -= pd.offsets.MonthEnd(5) tm.assert_index_equal(rng, expected) - def test_pi_add_offset_n_gt1(self, box): + def test_pi_add_offset_n_gt1(self, box_transpose_fail): # GH#23215 # add offset to PeriodIndex with freq.n > 1 + box, transpose = box_transpose_fail + per = pd.Period('2016-01', freq='2M') pi = pd.PeriodIndex([per]) expected = pd.PeriodIndex(['2016-03'], freq='2M') - pi = tm.box_expected(pi, box) - expected = tm.box_expected(expected, box) + + pi = tm.box_expected(pi, box, transpose=transpose) + expected = tm.box_expected(expected, box, transpose=transpose) result = pi + per.freq tm.assert_equal(result, expected) @@ -582,12 +575,14 @@ def test_pi_add_offset_n_gt1(self, box): def test_pi_add_offset_n_gt1_not_divisible(self, box_with_period): # GH#23215 # PeriodIndex with freq.n > 1 add offset with offset.n % freq.n != 0 + box = box_with_period pi = pd.PeriodIndex(['2016-01'], freq='2M') - pi = tm.box_expected(pi, box_with_period) - expected = pd.PeriodIndex(['2016-04'], freq='2M') - expected = tm.box_expected(expected, box_with_period) + + # FIXME: with transposing these tests fail + pi = tm.box_expected(pi, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = pi + to_offset('3M') tm.assert_equal(result, expected) @@ -801,14 +796,16 @@ def test_pi_add_sub_timedeltalike_freq_mismatch_monthly(self, with pytest.raises(period.IncompatibleFrequency, match=msg): rng -= other - def test_parr_add_sub_td64_nat(self, box): + def test_parr_add_sub_td64_nat(self, box_transpose_fail): # GH#23320 special handling for timedelta64("NaT") + box, transpose = box_transpose_fail + pi = pd.period_range("1994-04-01", periods=9, freq="19D") other = np.timedelta64("NaT") expected = pd.PeriodIndex(["NaT"] * 9, freq="19D") - obj = tm.box_expected(pi, box) - expected = tm.box_expected(expected, box) + obj = tm.box_expected(pi, box, transpose=transpose) + expected = tm.box_expected(expected, box, transpose=transpose) result = obj + other tm.assert_equal(result, expected) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 50c0e9564e02d..58c8b3b07f723 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -367,10 +367,6 @@ def test_td64arr_add_str_invalid(self, box): operator.sub, ops.rsub], ids=lambda x: x.__name__) def test_td64arr_add_sub_float(self, box, op, other): - if box is pd.DataFrame and isinstance(other, np.ndarray): - pytest.xfail("Tries to broadcast, raising " - "ValueError instead of TypeError") - tdi = TimedeltaIndex(['-1 days', '-1 days']) tdi = tm.box_expected(tdi, box) @@ -393,9 +389,8 @@ def test_td64arr_sub_period(self, box, freq): @pytest.mark.parametrize('pi_freq', ['D', 'W', 'Q', 'H']) @pytest.mark.parametrize('tdi_freq', [None, 'H']) - def test_td64arr_sub_pi(self, box_df_broadcast_failure, tdi_freq, pi_freq): + def test_td64arr_sub_pi(self, box, tdi_freq, pi_freq): # GH#20049 subtracting PeriodIndex should raise TypeError - box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 hours', '2 hours'], freq=tdi_freq) dti = Timestamp('2018-03-07 17:16:40') + tdi pi = dti.to_period(pi_freq) @@ -427,8 +422,10 @@ def test_td64arr_add_timestamp(self, box, tz_naive_fixture): idx = TimedeltaIndex(['1 day', '2 day']) expected = DatetimeIndex(['2011-01-02', '2011-01-03'], tz=tz) - idx = tm.box_expected(idx, box) - expected = tm.box_expected(expected, box) + # FIXME: fails with transpose=True because of tz-aware DataFrame + # transpose bug + idx = tm.box_expected(idx, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = idx + other tm.assert_equal(result, expected) @@ -460,9 +457,7 @@ def test_td64arr_add_sub_timestamp(self, box): with pytest.raises(TypeError): tdser - ts - def test_tdi_sub_dt64_array(self, box_df_broadcast_failure): - box = box_df_broadcast_failure - + def test_tdi_sub_dt64_array(self, box): dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) dtarr = dti.values @@ -478,9 +473,7 @@ def test_tdi_sub_dt64_array(self, box_df_broadcast_failure): result = dtarr - tdi tm.assert_equal(result, expected) - def test_tdi_add_dt64_array(self, box_df_broadcast_failure): - box = box_df_broadcast_failure - + def test_tdi_add_dt64_array(self, box): dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) dtarr = dti.values @@ -524,9 +517,8 @@ def test_td64arr_add_int_series_invalid(self, box, tdser): with pytest.raises(err): int_ser - tdser - def test_td64arr_add_intlike(self, box_df_broadcast_failure): + def test_td64arr_add_intlike(self, box): # GH#19123 - box = box_df_broadcast_failure tdi = TimedeltaIndex(['59 days', '59 days', 'NaT']) ser = tm.box_expected(tdi, box) err = TypeError if box is not pd.Index else NullFrequencyError @@ -580,9 +572,6 @@ def test_td64arr_add_sub_numeric_scalar_invalid(self, box, scalar, tdser): # TODO: Add DataFrame in here? ], ids=lambda x: type(x).__name__) def test_td64arr_add_sub_numeric_arr_invalid(self, box, vec, dtype, tdser): - if box is pd.DataFrame and not isinstance(vec, Series): - raise pytest.xfail(reason="Tries to broadcast incorrectly") - tdser = tm.box_expected(tdser, box) err = TypeError if box is pd.Index and not dtype.startswith('float'): @@ -655,9 +644,7 @@ def test_timedelta64_operations_with_timedeltas(self): # roundtrip tm.assert_series_equal(result + td2, td1) - def test_td64arr_add_td64_array(self, box_df_broadcast_failure): - box = box_df_broadcast_failure - + def test_td64arr_add_td64_array(self, box): dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) tdarr = tdi.values @@ -671,9 +658,7 @@ def test_td64arr_add_td64_array(self, box_df_broadcast_failure): result = tdarr + tdi tm.assert_equal(result, expected) - def test_td64arr_sub_td64_array(self, box_df_broadcast_failure): - box = box_df_broadcast_failure - + def test_td64arr_sub_td64_array(self, box): dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) tdarr = tdi.values @@ -691,10 +676,13 @@ def test_td64arr_sub_td64_array(self, box_df_broadcast_failure): @pytest.mark.parametrize('names', [(None, None, None), ('Egon', 'Venkman', None), ('NCC1701D', 'NCC1701D', 'NCC1701D')]) - def test_td64arr_add_sub_tdi(self, box_df_broadcast_failure, names): + def test_td64arr_add_sub_tdi(self, box, names): # GH#17250 make sure result dtype is correct # GH#19043 make sure names are propagated correctly - box = box_df_broadcast_failure + if box is pd.DataFrame and names[1] == 'Venkman': + pytest.skip("Name propagation for DataFrame does not behave like " + "it does for Index/Series") + tdi = TimedeltaIndex(['0 days', '1 day'], name=names[0]) ser = Series([Timedelta(hours=3), Timedelta(hours=4)], name=names[1]) expected = Series([Timedelta(hours=3), Timedelta(days=1, hours=4)], @@ -825,9 +813,12 @@ def test_timedelta64_operations_with_DateOffset(self): @pytest.mark.parametrize('names', [(None, None, None), ('foo', 'bar', None), ('foo', 'foo', 'foo')]) - def test_td64arr_add_offset_index(self, names, box_df_broadcast_failure): + def test_td64arr_add_offset_index(self, names, box): # GH#18849, GH#19744 - box = box_df_broadcast_failure + if box is pd.DataFrame and names[1] == 'bar': + pytest.skip("Name propagation for DataFrame does not behave like " + "it does for Index/Series") + tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'], name=names[0]) other = pd.Index([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)], @@ -838,19 +829,21 @@ def test_td64arr_add_offset_index(self, names, box_df_broadcast_failure): tdi = tm.box_expected(tdi, box) expected = tm.box_expected(expected, box) - with tm.assert_produces_warning(PerformanceWarning): + # The DataFrame operation is transposed and so operates as separate + # scalar operations, which do not issue a PerformanceWarning + warn = PerformanceWarning if box is not pd.DataFrame else None + with tm.assert_produces_warning(warn): res = tdi + other tm.assert_equal(res, expected) - with tm.assert_produces_warning(PerformanceWarning): + with tm.assert_produces_warning(warn): res2 = other + tdi tm.assert_equal(res2, expected) # TODO: combine with test_td64arr_add_offset_index by parametrizing # over second box? - def test_td64arr_add_offset_array(self, box_df_broadcast_failure): + def test_td64arr_add_offset_array(self, box): # GH#18849 - box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00']) other = np.array([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)]) @@ -860,20 +853,26 @@ def test_td64arr_add_offset_array(self, box_df_broadcast_failure): tdi = tm.box_expected(tdi, box) expected = tm.box_expected(expected, box) - with tm.assert_produces_warning(PerformanceWarning): + # The DataFrame operation is transposed and so operates as separate + # scalar operations, which do not issue a PerformanceWarning + warn = PerformanceWarning if box is not pd.DataFrame else None + with tm.assert_produces_warning(warn): res = tdi + other tm.assert_equal(res, expected) - with tm.assert_produces_warning(PerformanceWarning): + with tm.assert_produces_warning(warn): res2 = other + tdi tm.assert_equal(res2, expected) @pytest.mark.parametrize('names', [(None, None, None), ('foo', 'bar', None), ('foo', 'foo', 'foo')]) - def test_td64arr_sub_offset_index(self, names, box_df_broadcast_failure): + def test_td64arr_sub_offset_index(self, names, box): # GH#18824, GH#19744 - box = box_df_broadcast_failure + if box is pd.DataFrame and names[1] == 'bar': + pytest.skip("Name propagation for DataFrame does not behave like " + "it does for Index/Series") + tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'], name=names[0]) other = pd.Index([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)], @@ -885,13 +884,15 @@ def test_td64arr_sub_offset_index(self, names, box_df_broadcast_failure): tdi = tm.box_expected(tdi, box) expected = tm.box_expected(expected, box) - with tm.assert_produces_warning(PerformanceWarning): + # The DataFrame operation is transposed and so operates as separate + # scalar operations, which do not issue a PerformanceWarning + warn = PerformanceWarning if box is not pd.DataFrame else None + with tm.assert_produces_warning(warn): res = tdi - other tm.assert_equal(res, expected) - def test_td64arr_sub_offset_array(self, box_df_broadcast_failure): + def test_td64arr_sub_offset_array(self, box): # GH#18824 - box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00']) other = np.array([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)]) @@ -901,7 +902,10 @@ def test_td64arr_sub_offset_array(self, box_df_broadcast_failure): tdi = tm.box_expected(tdi, box) expected = tm.box_expected(expected, box) - with tm.assert_produces_warning(PerformanceWarning): + # The DataFrame operation is transposed and so operates as separate + # scalar operations, which do not issue a PerformanceWarning + warn = PerformanceWarning if box is not pd.DataFrame else None + with tm.assert_produces_warning(warn): res = tdi - other tm.assert_equal(res, expected) @@ -943,9 +947,6 @@ def test_td64arr_with_offset_series(self, names, box_df_fail): @pytest.mark.parametrize('obox', [np.array, pd.Index, pd.Series]) def test_td64arr_addsub_anchored_offset_arraylike(self, obox, box): # GH#18824 - if box is pd.DataFrame and obox is not pd.Series: - raise pytest.xfail(reason="Attempts to broadcast incorrectly") - tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00']) tdi = tm.box_expected(tdi, box) @@ -1023,8 +1024,7 @@ def test_tdi_mul_int_array_zerodim(self, box): result = idx * np.array(5, dtype='int64') tm.assert_equal(result, expected) - def test_tdi_mul_int_array(self, box_df_broadcast_failure): - box = box_df_broadcast_failure + def test_tdi_mul_int_array(self, box): rng5 = np.arange(5, dtype='int64') idx = TimedeltaIndex(rng5) expected = TimedeltaIndex(rng5 ** 2) @@ -1035,8 +1035,7 @@ def test_tdi_mul_int_array(self, box_df_broadcast_failure): result = idx * rng5 tm.assert_equal(result, expected) - def test_tdi_mul_int_series(self, box_df_fail): - box = box_df_fail + def test_tdi_mul_int_series(self, box): idx = TimedeltaIndex(np.arange(5, dtype='int64')) expected = TimedeltaIndex(np.arange(5, dtype='int64') ** 2) @@ -1048,8 +1047,7 @@ def test_tdi_mul_int_series(self, box_df_fail): result = idx * pd.Series(np.arange(5, dtype='int64')) tm.assert_equal(result, expected) - def test_tdi_mul_float_series(self, box_df_fail): - box = box_df_fail + def test_tdi_mul_float_series(self, box): idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) @@ -1069,9 +1067,7 @@ def test_tdi_mul_float_series(self, box_df_fail): pd.Float64Index(range(1, 11)), pd.RangeIndex(1, 11) ], ids=lambda x: type(x).__name__) - def test_tdi_rmul_arraylike(self, other, box_df_broadcast_failure): - box = box_df_broadcast_failure - + def test_tdi_rmul_arraylike(self, other, box): tdi = TimedeltaIndex(['1 Day'] * 10) expected = timedelta_range('1 days', '10 days') @@ -1131,8 +1127,8 @@ def test_td64arr_floordiv_tdscalar(self, box, scalar_td): expected = Series([0, 0, np.nan]) - td1 = tm.box_expected(td1, box) - expected = tm.box_expected(expected, box) + td1 = tm.box_expected(td1, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = td1 // scalar_td tm.assert_equal(result, expected) @@ -1144,8 +1140,8 @@ def test_td64arr_rfloordiv_tdscalar(self, box, scalar_td): expected = Series([1, 1, np.nan]) - td1 = tm.box_expected(td1, box) - expected = tm.box_expected(expected, box) + td1 = tm.box_expected(td1, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = scalar_td // td1 tm.assert_equal(result, expected) @@ -1157,8 +1153,8 @@ def test_td64arr_rfloordiv_tdscalar_explicit(self, box, scalar_td): expected = Series([1, 1, np.nan]) - td1 = tm.box_expected(td1, box) - expected = tm.box_expected(expected, box) + td1 = tm.box_expected(td1, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) # We can test __rfloordiv__ using this syntax, # see `test_timedelta_rfloordiv` @@ -1192,14 +1188,14 @@ def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, box): tdi = TimedeltaIndex(['00:05:03', '00:05:03', pd.NaT], freq=None) expected = pd.Index([2.0, 2.0, np.nan]) - tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, box) + tdi = tm.box_expected(tdi, box, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) res = tdi.__rfloordiv__(scalar_td) tm.assert_equal(res, expected) expected = pd.Index([0.0, 0.0, np.nan]) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, box, transpose=False) res = tdi // (scalar_td) tm.assert_equal(res, expected) @@ -1283,11 +1279,10 @@ def test_td64arr_div_numeric_scalar(self, box, two, tdser): Series([20, 30, 40])], ids=lambda x: type(x).__name__) @pytest.mark.parametrize('op', [operator.mul, ops.rmul]) - def test_td64arr_rmul_numeric_array(self, op, box_df_fail, + def test_td64arr_rmul_numeric_array(self, op, box, vector, dtype, tdser): # GH#4521 # divide/multiply by integers - box = box_df_fail # broadcasts incorrectly but doesn't raise vector = vector.astype(dtype) expected = Series(['1180 Days', '1770 Days', 'NaT'], @@ -1301,14 +1296,6 @@ def test_td64arr_rmul_numeric_array(self, op, box_df_fail, result = op(vector, tdser) tm.assert_equal(result, expected) - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="broadcasts along " - "wrong axis", - strict=True)) - ], ids=lambda x: x.__name__) @pytest.mark.parametrize('dtype', ['int64', 'int32', 'int16', 'uint64', 'uint32', 'uint16', 'uint8', 'float64', 'float32', 'float16']) diff --git a/pandas/util/testing.py b/pandas/util/testing.py index 748f3bbc5b497..1fa77f5321038 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -1587,7 +1587,7 @@ def assert_equal(left, right, **kwargs): raise NotImplementedError(type(left)) -def box_expected(expected, box_cls): +def box_expected(expected, box_cls, transpose=True): """ Helper function to wrap the expected output of a test in a given box_class. @@ -1606,6 +1606,11 @@ def box_expected(expected, box_cls): expected = pd.Series(expected) elif box_cls is pd.DataFrame: expected = pd.Series(expected).to_frame() + if transpose: + # for vector operations, we we need a DataFrame to be a single-row, + # not a single-column, in order to operate against non-DataFrame + # vectors of the same length. + expected = expected.T elif box_cls is PeriodArray: # the PeriodArray constructor is not as flexible as period_array expected = period_array(expected)