diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index a09efe6d4761c..a8e61b3fd9d3a 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -388,19 +388,11 @@ def test_td64arr_sub_period(self, box, freq): with pytest.raises(TypeError): p - idx - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="broadcasts along " - "wrong axis", - raises=ValueError, - strict=True)) - ], ids=lambda x: x.__name__) @pytest.mark.parametrize('pi_freq', ['D', 'W', 'Q', 'H']) @pytest.mark.parametrize('tdi_freq', [None, 'H']) - def test_td64arr_sub_pi(self, box, tdi_freq, pi_freq): + def test_td64arr_sub_pi(self, box_df_broadcast_failure, 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) @@ -529,16 +521,9 @@ def test_td64arr_rsub_int_series_invalid(self, box, tdser): with pytest.raises(err): Series([2, 3, 4]) - tdser - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Attempts to broadcast " - "incorrectly", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) - def test_td64arr_add_intlike(self, box): + def test_td64arr_add_intlike(self, box_df_broadcast_failure): # 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 @@ -706,21 +691,13 @@ def test_td64arr_sub_td64_array(self, box_df_broadcast_failure): tm.assert_equal(result, expected) # TODO: parametrize over [add, sub, radd, rsub]? - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Tries to broadcast " - "incorrectly leading " - "to alignment error", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) @pytest.mark.parametrize('names', [(None, None, None), ('Egon', 'Venkman', None), ('NCC1701D', 'NCC1701D', 'NCC1701D')]) - def test_td64arr_add_sub_tdi(self, box, names): + def test_td64arr_add_sub_tdi(self, box_df_broadcast_failure, names): # GH#17250 make sure result dtype is correct # GH#19043 make sure names are propagated correctly + box = box_df_broadcast_failure 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)], @@ -830,19 +807,12 @@ def test_timedelta64_operations_with_DateOffset(self): td - op(5) op(5) - td - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Tries to broadcast " - "incorrectly", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) @pytest.mark.parametrize('names', [(None, None, None), ('foo', 'bar', None), ('foo', 'foo', 'foo')]) - def test_td64arr_add_offset_index(self, names, box): + def test_td64arr_add_offset_index(self, names, box_df_broadcast_failure): # GH#18849, GH#19744 + box = box_df_broadcast_failure 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)], diff --git a/pandas/tests/frame/test_operators.py b/pandas/tests/frame/test_operators.py index 6ed289614b96a..433b0f09e13bc 100644 --- a/pandas/tests/frame/test_operators.py +++ b/pandas/tests/frame/test_operators.py @@ -27,38 +27,122 @@ from pandas.tests.frame.common import TestData, _check_mixed_float -class TestDataFrameOperators(TestData): +class TestDataFrameUnaryOperators(object): + # __pos__, __neg__, __inv__ + + @pytest.mark.parametrize('df,expected', [ + (pd.DataFrame({'a': [-1, 1]}), pd.DataFrame({'a': [1, -1]})), + (pd.DataFrame({'a': [False, True]}), + pd.DataFrame({'a': [True, False]})), + (pd.DataFrame({'a': pd.Series(pd.to_timedelta([-1, 1]))}), + pd.DataFrame({'a': pd.Series(pd.to_timedelta([1, -1]))})) + ]) + def test_neg_numeric(self, df, expected): + assert_frame_equal(-df, expected) + assert_series_equal(-df['a'], expected['a']) + + @pytest.mark.parametrize('df, expected', [ + (np.array([1, 2], dtype=object), np.array([-1, -2], dtype=object)), + ([Decimal('1.0'), Decimal('2.0')], [Decimal('-1.0'), Decimal('-2.0')]), + ]) + def test_neg_object(self, df, expected): + # GH#21380 + df = pd.DataFrame({'a': df}) + expected = pd.DataFrame({'a': expected}) + assert_frame_equal(-df, expected) + assert_series_equal(-df['a'], expected['a']) + + @pytest.mark.parametrize('df', [ + pd.DataFrame({'a': ['a', 'b']}), + pd.DataFrame({'a': pd.to_datetime(['2017-01-22', '1970-01-01'])}), + ]) + def test_neg_raises(self, df): + with pytest.raises(TypeError): + (- df) + with pytest.raises(TypeError): + (- df['a']) + + def test_invert(self): + _seriesd = tm.getSeriesData() + df = pd.DataFrame(_seriesd) + + assert_frame_equal(-(df < 0), ~(df < 0)) + + @pytest.mark.parametrize('df', [ + pd.DataFrame({'a': [-1, 1]}), + pd.DataFrame({'a': [False, True]}), + pd.DataFrame({'a': pd.Series(pd.to_timedelta([-1, 1]))}), + ]) + def test_pos_numeric(self, df): + # GH#16073 + assert_frame_equal(+df, df) + assert_series_equal(+df['a'], df['a']) + + @pytest.mark.parametrize('df', [ + # numpy changing behavior in the future + pytest.param(pd.DataFrame({'a': ['a', 'b']}), + marks=[pytest.mark.filterwarnings("ignore")]), + pd.DataFrame({'a': np.array([-1, 2], dtype=object)}), + pd.DataFrame({'a': [Decimal('-1.0'), Decimal('2.0')]}), + ]) + def test_pos_object(self, df): + # GH#21380 + assert_frame_equal(+df, df) + assert_series_equal(+df['a'], df['a']) + + @pytest.mark.parametrize('df', [ + pd.DataFrame({'a': pd.to_datetime(['2017-01-22', '1970-01-01'])}), + ]) + def test_pos_raises(self, df): + with pytest.raises(TypeError): + (+ df) + with pytest.raises(TypeError): + (+ df['a']) - def test_operators_boolean(self): - # GH 5808 +class TestDataFrameLogicalOperators(object): + # &, |, ^ + + def test_logical_ops_empty_frame(self): + # GH#5808 # empty frames, non-mixed dtype + df = DataFrame(index=[1]) + + result = df & df + assert_frame_equal(result, df) + + result = df | df + assert_frame_equal(result, df) + + df2 = DataFrame(index=[1, 2]) + result = df & df2 + assert_frame_equal(result, df2) - result = DataFrame(index=[1]) & DataFrame(index=[1]) - assert_frame_equal(result, DataFrame(index=[1])) + dfa = DataFrame(index=[1], columns=['A']) - result = DataFrame(index=[1]) | DataFrame(index=[1]) - assert_frame_equal(result, DataFrame(index=[1])) + result = dfa & dfa + assert_frame_equal(result, dfa) - result = DataFrame(index=[1]) & DataFrame(index=[1, 2]) - assert_frame_equal(result, DataFrame(index=[1, 2])) + def test_logical_ops_bool_frame(self): + # GH#5808 + df1a_bool = DataFrame(True, index=[1], columns=['A']) - result = DataFrame(index=[1], columns=['A']) & DataFrame( - index=[1], columns=['A']) - assert_frame_equal(result, DataFrame(index=[1], columns=['A'])) + result = df1a_bool & df1a_bool + assert_frame_equal(result, df1a_bool) - result = DataFrame(True, index=[1], columns=['A']) & DataFrame( - True, index=[1], columns=['A']) - assert_frame_equal(result, DataFrame(True, index=[1], columns=['A'])) + result = df1a_bool | df1a_bool + assert_frame_equal(result, df1a_bool) - result = DataFrame(True, index=[1], columns=['A']) | DataFrame( - True, index=[1], columns=['A']) - assert_frame_equal(result, DataFrame(True, index=[1], columns=['A'])) + def test_logical_ops_int_frame(self): + # GH#5808 + df1a_int = DataFrame(1, index=[1], columns=['A']) + df1a_bool = DataFrame(True, index=[1], columns=['A']) - # boolean ops - result = DataFrame(1, index=[1], columns=['A']) | DataFrame( - True, index=[1], columns=['A']) - assert_frame_equal(result, DataFrame(1, index=[1], columns=['A'])) + result = df1a_int | df1a_bool + assert_frame_equal(result, df1a_int) + + def test_logical_ops_invalid(self): + # GH#5808 df1 = DataFrame(1.0, index=[1], columns=['A']) df2 = DataFrame(True, index=[1], columns=['A']) @@ -70,6 +154,70 @@ def test_operators_boolean(self): with pytest.raises(TypeError): df1 | df2 + def test_logical_operators(self): + + def _check_bin_op(op): + result = op(df1, df2) + expected = DataFrame(op(df1.values, df2.values), index=df1.index, + columns=df1.columns) + assert result.values.dtype == np.bool_ + assert_frame_equal(result, expected) + + def _check_unary_op(op): + result = op(df1) + expected = DataFrame(op(df1.values), index=df1.index, + columns=df1.columns) + assert result.values.dtype == np.bool_ + assert_frame_equal(result, expected) + + df1 = {'a': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True}, + 'b': {'a': False, 'b': True, 'c': False, + 'd': False, 'e': False}, + 'c': {'a': False, 'b': False, 'c': True, + 'd': False, 'e': False}, + 'd': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True}, + 'e': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True}} + + df2 = {'a': {'a': True, 'b': False, 'c': True, 'd': False, 'e': False}, + 'b': {'a': False, 'b': True, 'c': False, + 'd': False, 'e': False}, + 'c': {'a': True, 'b': False, 'c': True, 'd': False, 'e': False}, + 'd': {'a': False, 'b': False, 'c': False, + 'd': True, 'e': False}, + 'e': {'a': False, 'b': False, 'c': False, + 'd': False, 'e': True}} + + df1 = DataFrame(df1) + df2 = DataFrame(df2) + + _check_bin_op(operator.and_) + _check_bin_op(operator.or_) + _check_bin_op(operator.xor) + + # operator.neg is deprecated in numpy >= 1.9 + _check_unary_op(operator.inv) # TODO: belongs elsewhere + + def test_logical_with_nas(self): + d = DataFrame({'a': [np.nan, False], 'b': [True, True]}) + + # GH4947 + # bool comparisons should return bool + result = d['a'] | d['b'] + expected = Series([False, True]) + assert_series_equal(result, expected) + + # GH4604, automatic casting here + result = d['a'].fillna(False) | d['b'] + expected = Series([True, True]) + assert_series_equal(result, expected) + + result = d['a'].fillna(False, downcast=False) | d['b'] + expected = Series([True, True]) + assert_series_equal(result, expected) + + +class TestDataFrameOperators(TestData): + @pytest.mark.parametrize('op', [operator.add, operator.sub, operator.mul, operator.truediv]) def test_operators_none_as_na(self, op): @@ -164,142 +312,15 @@ def test_timestamp_compare(self): result = right_f(Timestamp('nat'), df) assert_frame_equal(result, expected) - def test_logical_operators(self): - - def _check_bin_op(op): - result = op(df1, df2) - expected = DataFrame(op(df1.values, df2.values), index=df1.index, - columns=df1.columns) - assert result.values.dtype == np.bool_ - assert_frame_equal(result, expected) - - def _check_unary_op(op): - result = op(df1) - expected = DataFrame(op(df1.values), index=df1.index, - columns=df1.columns) - assert result.values.dtype == np.bool_ - assert_frame_equal(result, expected) - - df1 = {'a': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True}, - 'b': {'a': False, 'b': True, 'c': False, - 'd': False, 'e': False}, - 'c': {'a': False, 'b': False, 'c': True, - 'd': False, 'e': False}, - 'd': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True}, - 'e': {'a': True, 'b': False, 'c': False, 'd': True, 'e': True}} - - df2 = {'a': {'a': True, 'b': False, 'c': True, 'd': False, 'e': False}, - 'b': {'a': False, 'b': True, 'c': False, - 'd': False, 'e': False}, - 'c': {'a': True, 'b': False, 'c': True, 'd': False, 'e': False}, - 'd': {'a': False, 'b': False, 'c': False, - 'd': True, 'e': False}, - 'e': {'a': False, 'b': False, 'c': False, - 'd': False, 'e': True}} - - df1 = DataFrame(df1) - df2 = DataFrame(df2) - - _check_bin_op(operator.and_) - _check_bin_op(operator.or_) - _check_bin_op(operator.xor) - - # operator.neg is deprecated in numpy >= 1.9 - _check_unary_op(operator.inv) - @pytest.mark.parametrize('op,res', [('__eq__', False), ('__ne__', True)]) - # not sure what's correct here. + # TODO: not sure what's correct here. @pytest.mark.filterwarnings("ignore:elementwise:FutureWarning") def test_logical_typeerror_with_non_valid(self, op, res): # we are comparing floats vs a string result = getattr(self.frame, op)('foo') assert bool(result.all().all()) is res - def test_logical_with_nas(self): - d = DataFrame({'a': [np.nan, False], 'b': [True, True]}) - - # GH4947 - # bool comparisons should return bool - result = d['a'] | d['b'] - expected = Series([False, True]) - assert_series_equal(result, expected) - - # GH4604, automatic casting here - result = d['a'].fillna(False) | d['b'] - expected = Series([True, True]) - assert_series_equal(result, expected) - - result = d['a'].fillna(False, downcast=False) | d['b'] - expected = Series([True, True]) - assert_series_equal(result, expected) - - @pytest.mark.parametrize('df,expected', [ - (pd.DataFrame({'a': [-1, 1]}), pd.DataFrame({'a': [1, -1]})), - (pd.DataFrame({'a': [False, True]}), - pd.DataFrame({'a': [True, False]})), - (pd.DataFrame({'a': pd.Series(pd.to_timedelta([-1, 1]))}), - pd.DataFrame({'a': pd.Series(pd.to_timedelta([1, -1]))})) - ]) - def test_neg_numeric(self, df, expected): - assert_frame_equal(-df, expected) - assert_series_equal(-df['a'], expected['a']) - - @pytest.mark.parametrize('df, expected', [ - (np.array([1, 2], dtype=object), np.array([-1, -2], dtype=object)), - ([Decimal('1.0'), Decimal('2.0')], [Decimal('-1.0'), Decimal('-2.0')]), - ]) - def test_neg_object(self, df, expected): - # GH 21380 - df = pd.DataFrame({'a': df}) - expected = pd.DataFrame({'a': expected}) - assert_frame_equal(-df, expected) - assert_series_equal(-df['a'], expected['a']) - - @pytest.mark.parametrize('df', [ - pd.DataFrame({'a': ['a', 'b']}), - pd.DataFrame({'a': pd.to_datetime(['2017-01-22', '1970-01-01'])}), - ]) - def test_neg_raises(self, df): - with pytest.raises(TypeError): - (- df) - with pytest.raises(TypeError): - (- df['a']) - - def test_invert(self): - assert_frame_equal(-(self.frame < 0), ~(self.frame < 0)) - - @pytest.mark.parametrize('df', [ - pd.DataFrame({'a': [-1, 1]}), - pd.DataFrame({'a': [False, True]}), - pd.DataFrame({'a': pd.Series(pd.to_timedelta([-1, 1]))}), - ]) - def test_pos_numeric(self, df): - # GH 16073 - assert_frame_equal(+df, df) - assert_series_equal(+df['a'], df['a']) - - @pytest.mark.parametrize('df', [ - # numpy changing behavior in the future - pytest.param(pd.DataFrame({'a': ['a', 'b']}), - marks=[pytest.mark.filterwarnings("ignore")]), - pd.DataFrame({'a': np.array([-1, 2], dtype=object)}), - pd.DataFrame({'a': [Decimal('-1.0'), Decimal('2.0')]}), - ]) - def test_pos_object(self, df): - # GH 21380 - assert_frame_equal(+df, df) - assert_series_equal(+df['a'], df['a']) - - @pytest.mark.parametrize('df', [ - pd.DataFrame({'a': pd.to_datetime(['2017-01-22', '1970-01-01'])}), - ]) - def test_pos_raises(self, df): - with pytest.raises(TypeError): - (+ df) - with pytest.raises(TypeError): - (+ df['a']) - def test_binary_ops_align(self): # test aligning binary ops diff --git a/pandas/tests/frame/test_period.py b/pandas/tests/frame/test_period.py index d56df2371b2e3..d52b848bebad1 100644 --- a/pandas/tests/frame/test_period.py +++ b/pandas/tests/frame/test_period.py @@ -14,9 +14,6 @@ def _permute(obj): class TestPeriodIndex(object): - def setup_method(self, method): - pass - def test_as_frame_columns(self): rng = period_range('1/1/2000', periods=5) df = DataFrame(randn(10, 5), columns=rng) diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index b1d9d362d1402..40089c8e9e477 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -182,7 +182,7 @@ def test_frame_ctor_datetime64_column(self): df = DataFrame({'A': np.random.randn(len(rng)), 'B': dates}) assert np.issubdtype(df['B'].dtype, np.dtype('M8[ns]')) - def test_frame_add_datetime64_column(self): + def test_frame_append_datetime64_column(self): rng = date_range('1/1/2000 00:00:00', '1/1/2000 1:59:50', freq='10s') df = DataFrame(index=np.arange(len(rng))) @@ -195,7 +195,7 @@ def test_frame_datetime64_pre1900_repr(self): # it works! repr(df) - def test_frame_add_datetime64_col_other_units(self): + def test_frame_append_datetime64_col_other_units(self): n = 100 units = ['h', 'm', 's', 'ms', 'D', 'M', 'Y'] diff --git a/pandas/tests/series/test_operators.py b/pandas/tests/series/test_operators.py index f3ab197771d53..55e3dfde3ceb7 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -25,6 +25,361 @@ from .common import TestData +class TestSeriesLogicalOps(object): + @pytest.mark.parametrize('bool_op', [operator.and_, + operator.or_, operator.xor]) + def test_bool_operators_with_nas(self, bool_op): + # boolean &, |, ^ should work with object arrays and propagate NAs + ser = Series(bdate_range('1/1/2000', periods=10), dtype=object) + ser[::2] = np.nan + + mask = ser.isna() + filled = ser.fillna(ser[0]) + + result = bool_op(ser < ser[9], ser > ser[3]) + + expected = bool_op(filled < filled[9], filled > filled[3]) + expected[mask] = False + assert_series_equal(result, expected) + + def test_operators_bitwise(self): + # GH#9016: support bitwise op for integer types + index = list('bca') + + s_tft = Series([True, False, True], index=index) + s_fff = Series([False, False, False], index=index) + s_tff = Series([True, False, False], index=index) + s_empty = Series([]) + + # TODO: unused + # s_0101 = Series([0, 1, 0, 1]) + + s_0123 = Series(range(4), dtype='int64') + s_3333 = Series([3] * 4) + s_4444 = Series([4] * 4) + + res = s_tft & s_empty + expected = s_fff + assert_series_equal(res, expected) + + res = s_tft | s_empty + expected = s_tft + assert_series_equal(res, expected) + + res = s_0123 & s_3333 + expected = Series(range(4), dtype='int64') + assert_series_equal(res, expected) + + res = s_0123 | s_4444 + expected = Series(range(4, 8), dtype='int64') + assert_series_equal(res, expected) + + s_a0b1c0 = Series([1], list('b')) + + res = s_tft & s_a0b1c0 + expected = s_tff.reindex(list('abc')) + assert_series_equal(res, expected) + + res = s_tft | s_a0b1c0 + expected = s_tft.reindex(list('abc')) + assert_series_equal(res, expected) + + n0 = 0 + res = s_tft & n0 + expected = s_fff + assert_series_equal(res, expected) + + res = s_0123 & n0 + expected = Series([0] * 4) + assert_series_equal(res, expected) + + n1 = 1 + res = s_tft & n1 + expected = s_tft + assert_series_equal(res, expected) + + res = s_0123 & n1 + expected = Series([0, 1, 0, 1]) + assert_series_equal(res, expected) + + s_1111 = Series([1] * 4, dtype='int8') + res = s_0123 & s_1111 + expected = Series([0, 1, 0, 1], dtype='int64') + assert_series_equal(res, expected) + + res = s_0123.astype(np.int16) | s_1111.astype(np.int32) + expected = Series([1, 1, 3, 3], dtype='int32') + assert_series_equal(res, expected) + + with pytest.raises(TypeError): + s_1111 & 'a' + with pytest.raises(TypeError): + s_1111 & ['a', 'b', 'c', 'd'] + with pytest.raises(TypeError): + s_0123 & np.NaN + with pytest.raises(TypeError): + s_0123 & 3.14 + with pytest.raises(TypeError): + s_0123 & [0.1, 4, 3.14, 2] + + # s_0123 will be all false now because of reindexing like s_tft + if compat.PY3: + # unable to sort incompatible object via .union. + exp = Series([False] * 7, index=['b', 'c', 'a', 0, 1, 2, 3]) + with tm.assert_produces_warning(RuntimeWarning): + assert_series_equal(s_tft & s_0123, exp) + else: + exp = Series([False] * 7, index=[0, 1, 2, 3, 'a', 'b', 'c']) + assert_series_equal(s_tft & s_0123, exp) + + # s_tft will be all false now because of reindexing like s_0123 + if compat.PY3: + # unable to sort incompatible object via .union. + exp = Series([False] * 7, index=[0, 1, 2, 3, 'b', 'c', 'a']) + with tm.assert_produces_warning(RuntimeWarning): + assert_series_equal(s_0123 & s_tft, exp) + else: + exp = Series([False] * 7, index=[0, 1, 2, 3, 'a', 'b', 'c']) + assert_series_equal(s_0123 & s_tft, exp) + + assert_series_equal(s_0123 & False, Series([False] * 4)) + assert_series_equal(s_0123 ^ False, Series([False, True, True, True])) + assert_series_equal(s_0123 & [False], Series([False] * 4)) + assert_series_equal(s_0123 & (False), Series([False] * 4)) + assert_series_equal(s_0123 & Series([False, np.NaN, False, False]), + Series([False] * 4)) + + s_ftft = Series([False, True, False, True]) + assert_series_equal(s_0123 & Series([0.1, 4, -3.14, 2]), s_ftft) + + s_abNd = Series(['a', 'b', np.NaN, 'd']) + res = s_0123 & s_abNd + expected = s_ftft + assert_series_equal(res, expected) + + def test_scalar_na_logical_ops_corners(self): + s = Series([2, 3, 4, 5, 6, 7, 8, 9, 10]) + + with pytest.raises(TypeError): + s & datetime(2005, 1, 1) + + s = Series([2, 3, 4, 5, 6, 7, 8, 9, datetime(2005, 1, 1)]) + s[::2] = np.nan + + expected = Series(True, index=s.index) + expected[::2] = False + result = s & list(s) + assert_series_equal(result, expected) + + d = DataFrame({'A': s}) + # TODO: Fix this exception - needs to be fixed! (see GH5035) + # (previously this was a TypeError because series returned + # NotImplemented + + # this is an alignment issue; these are equivalent + # https://github.com/pandas-dev/pandas/issues/5284 + + with pytest.raises(TypeError): + d.__and__(s, axis='columns') + + with pytest.raises(TypeError): + s & d + + # this is wrong as its not a boolean result + # result = d.__and__(s,axis='index') + + @pytest.mark.parametrize('op', [ + operator.and_, + operator.or_, + operator.xor, + pytest.param(ops.rand_, + marks=pytest.mark.xfail(reason="GH#22092 Index " + "implementation returns " + "Index", + raises=AssertionError, + strict=True)), + pytest.param(ops.ror_, + marks=pytest.mark.xfail(reason="GH#22092 Index " + "implementation raises", + raises=ValueError, strict=True)), + pytest.param(ops.rxor, + marks=pytest.mark.xfail(reason="GH#22092 Index " + "implementation raises", + raises=TypeError, strict=True)) + ]) + def test_logical_ops_with_index(self, op): + # GH#22092, GH#19792 + ser = Series([True, True, False, False]) + idx1 = Index([True, False, True, False]) + idx2 = Index([1, 0, 1, 0]) + + expected = Series([op(ser[n], idx1[n]) for n in range(len(ser))]) + + result = op(ser, idx1) + assert_series_equal(result, expected) + + expected = Series([op(ser[n], idx2[n]) for n in range(len(ser))], + dtype=bool) + + result = op(ser, idx2) + assert_series_equal(result, expected) + + def test_logical_ops_label_based(self): + # GH#4947 + # logical ops should be label based + + a = Series([True, False, True], list('bca')) + b = Series([False, True, False], list('abc')) + + expected = Series([False, True, False], list('abc')) + result = a & b + assert_series_equal(result, expected) + + expected = Series([True, True, False], list('abc')) + result = a | b + assert_series_equal(result, expected) + + expected = Series([True, False, False], list('abc')) + result = a ^ b + assert_series_equal(result, expected) + + # rhs is bigger + a = Series([True, False, True], list('bca')) + b = Series([False, True, False, True], list('abcd')) + + expected = Series([False, True, False, False], list('abcd')) + result = a & b + assert_series_equal(result, expected) + + expected = Series([True, True, False, False], list('abcd')) + result = a | b + assert_series_equal(result, expected) + + # filling + + # vs empty + result = a & Series([]) + expected = Series([False, False, False], list('bca')) + assert_series_equal(result, expected) + + result = a | Series([]) + expected = Series([True, False, True], list('bca')) + assert_series_equal(result, expected) + + # vs non-matching + result = a & Series([1], ['z']) + expected = Series([False, False, False, False], list('abcz')) + assert_series_equal(result, expected) + + result = a | Series([1], ['z']) + expected = Series([True, True, False, False], list('abcz')) + assert_series_equal(result, expected) + + # identity + # we would like s[s|e] == s to hold for any e, whether empty or not + for e in [Series([]), Series([1], ['z']), + Series(np.nan, b.index), Series(np.nan, a.index)]: + result = a[a | e] + assert_series_equal(result, a[a]) + + for e in [Series(['z'])]: + if compat.PY3: + with tm.assert_produces_warning(RuntimeWarning): + result = a[a | e] + else: + result = a[a | e] + assert_series_equal(result, a[a]) + + # vs scalars + index = list('bca') + t = Series([True, False, True]) + + for v in [True, 1, 2]: + result = Series([True, False, True], index=index) | v + expected = Series([True, True, True], index=index) + assert_series_equal(result, expected) + + for v in [np.nan, 'foo']: + with pytest.raises(TypeError): + t | v + + for v in [False, 0]: + result = Series([True, False, True], index=index) | v + expected = Series([True, False, True], index=index) + assert_series_equal(result, expected) + + for v in [True, 1]: + result = Series([True, False, True], index=index) & v + expected = Series([True, False, True], index=index) + assert_series_equal(result, expected) + + for v in [False, 0]: + result = Series([True, False, True], index=index) & v + expected = Series([False, False, False], index=index) + assert_series_equal(result, expected) + for v in [np.nan]: + with pytest.raises(TypeError): + t & v + + def test_logical_ops_df_compat(self): + # GH#1134 + s1 = pd.Series([True, False, True], index=list('ABC'), name='x') + s2 = pd.Series([True, True, False], index=list('ABD'), name='x') + + exp = pd.Series([True, False, False, False], + index=list('ABCD'), name='x') + assert_series_equal(s1 & s2, exp) + assert_series_equal(s2 & s1, exp) + + # True | np.nan => True + exp = pd.Series([True, True, True, False], + index=list('ABCD'), name='x') + assert_series_equal(s1 | s2, exp) + # np.nan | True => np.nan, filled with False + exp = pd.Series([True, True, False, False], + index=list('ABCD'), name='x') + assert_series_equal(s2 | s1, exp) + + # DataFrame doesn't fill nan with False + exp = pd.DataFrame({'x': [True, False, np.nan, np.nan]}, + index=list('ABCD')) + assert_frame_equal(s1.to_frame() & s2.to_frame(), exp) + assert_frame_equal(s2.to_frame() & s1.to_frame(), exp) + + exp = pd.DataFrame({'x': [True, True, np.nan, np.nan]}, + index=list('ABCD')) + assert_frame_equal(s1.to_frame() | s2.to_frame(), exp) + assert_frame_equal(s2.to_frame() | s1.to_frame(), exp) + + # different length + s3 = pd.Series([True, False, True], index=list('ABC'), name='x') + s4 = pd.Series([True, True, True, True], index=list('ABCD'), name='x') + + exp = pd.Series([True, False, True, False], + index=list('ABCD'), name='x') + assert_series_equal(s3 & s4, exp) + assert_series_equal(s4 & s3, exp) + + # np.nan | True => np.nan, filled with False + exp = pd.Series([True, True, True, False], + index=list('ABCD'), name='x') + assert_series_equal(s3 | s4, exp) + # True | np.nan => True + exp = pd.Series([True, True, True, True], + index=list('ABCD'), name='x') + assert_series_equal(s4 | s3, exp) + + exp = pd.DataFrame({'x': [True, False, True, np.nan]}, + index=list('ABCD')) + assert_frame_equal(s3.to_frame() & s4.to_frame(), exp) + assert_frame_equal(s4.to_frame() & s3.to_frame(), exp) + + exp = pd.DataFrame({'x': [True, True, True, np.nan]}, + index=list('ABCD')) + assert_frame_equal(s3.to_frame() | s4.to_frame(), exp) + assert_frame_equal(s4.to_frame() | s3.to_frame(), exp) + + class TestSeriesComparisons(object): def test_comparisons(self): left = np.random.randn(10) @@ -164,22 +519,6 @@ def test_comparison_operators_with_nas(self): # expected = f(val, s.dropna()).reindex(s.index) # assert_series_equal(result, expected) - @pytest.mark.parametrize('bool_op', [operator.and_, - operator.or_, operator.xor]) - def test_bool_operators_with_nas(self, bool_op): - # boolean &, |, ^ should work with object arrays and propagate NAs - ser = Series(bdate_range('1/1/2000', periods=10), dtype=object) - ser[::2] = np.nan - - mask = ser.isna() - filled = ser.fillna(ser[0]) - - result = bool_op(ser < ser[9], ser > ser[3]) - - expected = bool_op(filled < filled[9], filled > filled[3]) - expected[mask] = False - assert_series_equal(result, expected) - def test_unequal_categorical_comparison_raises_type_error(self): # unequal comparison should raise for unordered cats cat = Series(Categorical(list("abc"))) @@ -258,104 +597,44 @@ def test_comparison_different_length(self): with pytest.raises(ValueError): a == b - def test_comparison_label_based(self): - - # GH 4947 - # comparisons should be label based - - a = Series([True, False, True], list('bca')) - b = Series([False, True, False], list('abc')) - - expected = Series([False, True, False], list('abc')) - result = a & b - assert_series_equal(result, expected) - - expected = Series([True, True, False], list('abc')) - result = a | b - assert_series_equal(result, expected) - - expected = Series([True, False, False], list('abc')) - result = a ^ b - assert_series_equal(result, expected) - - # rhs is bigger - a = Series([True, False, True], list('bca')) - b = Series([False, True, False, True], list('abcd')) - - expected = Series([False, True, False, False], list('abcd')) - result = a & b - assert_series_equal(result, expected) - - expected = Series([True, True, False, False], list('abcd')) - result = a | b - assert_series_equal(result, expected) - - # filling - - # vs empty - result = a & Series([]) - expected = Series([False, False, False], list('bca')) - assert_series_equal(result, expected) - - result = a | Series([]) - expected = Series([True, False, True], list('bca')) - assert_series_equal(result, expected) + def test_ne(self): + ts = Series([3, 4, 5, 6, 7], [3, 4, 5, 6, 7], dtype=float) + expected = [True, True, False, True, True] + assert tm.equalContents(ts.index != 5, expected) + assert tm.equalContents(~(ts.index == 5), expected) - # vs non-matching - result = a & Series([1], ['z']) - expected = Series([False, False, False, False], list('abcz')) - assert_series_equal(result, expected) + def test_comp_ops_df_compat(self): + # GH 1134 + s1 = pd.Series([1, 2, 3], index=list('ABC'), name='x') + s2 = pd.Series([2, 2, 2], index=list('ABD'), name='x') - result = a | Series([1], ['z']) - expected = Series([True, True, False, False], list('abcz')) - assert_series_equal(result, expected) + s3 = pd.Series([1, 2, 3], index=list('ABC'), name='x') + s4 = pd.Series([2, 2, 2, 2], index=list('ABCD'), name='x') - # identity - # we would like s[s|e] == s to hold for any e, whether empty or not - for e in [Series([]), Series([1], ['z']), - Series(np.nan, b.index), Series(np.nan, a.index)]: - result = a[a | e] - assert_series_equal(result, a[a]) + for left, right in [(s1, s2), (s2, s1), (s3, s4), (s4, s3)]: - for e in [Series(['z'])]: - if compat.PY3: - with tm.assert_produces_warning(RuntimeWarning): - result = a[a | e] - else: - result = a[a | e] - assert_series_equal(result, a[a]) + msg = "Can only compare identically-labeled Series objects" + with tm.assert_raises_regex(ValueError, msg): + left == right - # vs scalars - index = list('bca') - t = Series([True, False, True]) + with tm.assert_raises_regex(ValueError, msg): + left != right - for v in [True, 1, 2]: - result = Series([True, False, True], index=index) | v - expected = Series([True, True, True], index=index) - assert_series_equal(result, expected) + with tm.assert_raises_regex(ValueError, msg): + left < right - for v in [np.nan, 'foo']: - with pytest.raises(TypeError): - t | v + msg = "Can only compare identically-labeled DataFrame objects" + with tm.assert_raises_regex(ValueError, msg): + left.to_frame() == right.to_frame() - for v in [False, 0]: - result = Series([True, False, True], index=index) | v - expected = Series([True, False, True], index=index) - assert_series_equal(result, expected) + with tm.assert_raises_regex(ValueError, msg): + left.to_frame() != right.to_frame() - for v in [True, 1]: - result = Series([True, False, True], index=index) & v - expected = Series([True, False, True], index=index) - assert_series_equal(result, expected) + with tm.assert_raises_regex(ValueError, msg): + left.to_frame() < right.to_frame() - for v in [False, 0]: - result = Series([True, False, True], index=index) & v - expected = Series([False, False, False], index=index) - assert_series_equal(result, expected) - for v in [np.nan]: - with pytest.raises(TypeError): - t & v +class TestSeriesFlexComparisonOps(object): def test_comparison_flex_basic(self): left = pd.Series(np.random.randn(10)) right = pd.Series(np.random.randn(10)) @@ -414,53 +693,17 @@ def test_comparison_flex_alignment_fill(self): exp = pd.Series([True, True, False, False], index=list('abcd')) assert_series_equal(left.ne(right, fill_value=2), exp) - exp = pd.Series([False, False, True, True], index=list('abcd')) - assert_series_equal(left.le(right, fill_value=0), exp) - - exp = pd.Series([False, False, False, True], index=list('abcd')) - assert_series_equal(left.lt(right, fill_value=0), exp) - - exp = pd.Series([True, True, True, False], index=list('abcd')) - assert_series_equal(left.ge(right, fill_value=0), exp) - - exp = pd.Series([True, True, False, False], index=list('abcd')) - assert_series_equal(left.gt(right, fill_value=0), exp) - - def test_ne(self): - ts = Series([3, 4, 5, 6, 7], [3, 4, 5, 6, 7], dtype=float) - expected = [True, True, False, True, True] - assert tm.equalContents(ts.index != 5, expected) - assert tm.equalContents(~(ts.index == 5), expected) - - def test_comp_ops_df_compat(self): - # GH 1134 - s1 = pd.Series([1, 2, 3], index=list('ABC'), name='x') - s2 = pd.Series([2, 2, 2], index=list('ABD'), name='x') - - s3 = pd.Series([1, 2, 3], index=list('ABC'), name='x') - s4 = pd.Series([2, 2, 2, 2], index=list('ABCD'), name='x') - - for left, right in [(s1, s2), (s2, s1), (s3, s4), (s4, s3)]: - - msg = "Can only compare identically-labeled Series objects" - with tm.assert_raises_regex(ValueError, msg): - left == right - - with tm.assert_raises_regex(ValueError, msg): - left != right - - with tm.assert_raises_regex(ValueError, msg): - left < right - - msg = "Can only compare identically-labeled DataFrame objects" - with tm.assert_raises_regex(ValueError, msg): - left.to_frame() == right.to_frame() + exp = pd.Series([False, False, True, True], index=list('abcd')) + assert_series_equal(left.le(right, fill_value=0), exp) - with tm.assert_raises_regex(ValueError, msg): - left.to_frame() != right.to_frame() + exp = pd.Series([False, False, False, True], index=list('abcd')) + assert_series_equal(left.lt(right, fill_value=0), exp) - with tm.assert_raises_regex(ValueError, msg): - left.to_frame() < right.to_frame() + exp = pd.Series([True, True, True, False], index=list('abcd')) + assert_series_equal(left.ge(right, fill_value=0), exp) + + exp = pd.Series([True, True, False, False], index=list('abcd')) + assert_series_equal(left.gt(right, fill_value=0), exp) class TestDatetimeSeriesArithmetic(object): @@ -577,12 +820,6 @@ def test_op_method(self, opname, ts): expected = alt(other, series) assert_almost_equal(result, expected) - def test_neg(self): - assert_series_equal(-self.series, -1 * self.series) - - def test_invert(self): - assert_series_equal(-(self.series < 0), ~(self.series < 0)) - def test_operators_empty_int_corner(self): s1 = Series([], [], dtype=np.int32) s2 = Series({'x': 0.}) @@ -604,188 +841,6 @@ def test_ops_datetimelike_align(self): result = (dt2.to_frame() - dt.to_frame())[0] assert_series_equal(result, expected) - @pytest.mark.parametrize('op', [ - operator.and_, - operator.or_, - operator.xor, - pytest.param(ops.rand_, - marks=pytest.mark.xfail(reason="GH#22092 Index " - "implementation returns " - "Index", - raises=AssertionError, - strict=True)), - pytest.param(ops.ror_, - marks=pytest.mark.xfail(reason="GH#22092 Index " - "implementation raises", - raises=ValueError, strict=True)), - pytest.param(ops.rxor, - marks=pytest.mark.xfail(reason="GH#22092 Index " - "implementation raises", - raises=TypeError, strict=True)) - ]) - def test_bool_ops_with_index(self, op): - # GH#22092, GH#19792 - ser = Series([True, True, False, False]) - idx1 = Index([True, False, True, False]) - idx2 = Index([1, 0, 1, 0]) - - expected = Series([op(ser[n], idx1[n]) for n in range(len(ser))]) - - result = op(ser, idx1) - assert_series_equal(result, expected) - - expected = Series([op(ser[n], idx2[n]) for n in range(len(ser))], - dtype=bool) - - result = op(ser, idx2) - assert_series_equal(result, expected) - - def test_operators_bitwise(self): - # GH 9016: support bitwise op for integer types - index = list('bca') - - s_tft = Series([True, False, True], index=index) - s_fff = Series([False, False, False], index=index) - s_tff = Series([True, False, False], index=index) - s_empty = Series([]) - - # TODO: unused - # s_0101 = Series([0, 1, 0, 1]) - - s_0123 = Series(range(4), dtype='int64') - s_3333 = Series([3] * 4) - s_4444 = Series([4] * 4) - - res = s_tft & s_empty - expected = s_fff - assert_series_equal(res, expected) - - res = s_tft | s_empty - expected = s_tft - assert_series_equal(res, expected) - - res = s_0123 & s_3333 - expected = Series(range(4), dtype='int64') - assert_series_equal(res, expected) - - res = s_0123 | s_4444 - expected = Series(range(4, 8), dtype='int64') - assert_series_equal(res, expected) - - s_a0b1c0 = Series([1], list('b')) - - res = s_tft & s_a0b1c0 - expected = s_tff.reindex(list('abc')) - assert_series_equal(res, expected) - - res = s_tft | s_a0b1c0 - expected = s_tft.reindex(list('abc')) - assert_series_equal(res, expected) - - n0 = 0 - res = s_tft & n0 - expected = s_fff - assert_series_equal(res, expected) - - res = s_0123 & n0 - expected = Series([0] * 4) - assert_series_equal(res, expected) - - n1 = 1 - res = s_tft & n1 - expected = s_tft - assert_series_equal(res, expected) - - res = s_0123 & n1 - expected = Series([0, 1, 0, 1]) - assert_series_equal(res, expected) - - s_1111 = Series([1] * 4, dtype='int8') - res = s_0123 & s_1111 - expected = Series([0, 1, 0, 1], dtype='int64') - assert_series_equal(res, expected) - - res = s_0123.astype(np.int16) | s_1111.astype(np.int32) - expected = Series([1, 1, 3, 3], dtype='int32') - assert_series_equal(res, expected) - - with pytest.raises(TypeError): - s_1111 & 'a' - with pytest.raises(TypeError): - s_1111 & ['a', 'b', 'c', 'd'] - with pytest.raises(TypeError): - s_0123 & np.NaN - with pytest.raises(TypeError): - s_0123 & 3.14 - with pytest.raises(TypeError): - s_0123 & [0.1, 4, 3.14, 2] - - # s_0123 will be all false now because of reindexing like s_tft - if compat.PY3: - # unable to sort incompatible object via .union. - exp = Series([False] * 7, index=['b', 'c', 'a', 0, 1, 2, 3]) - with tm.assert_produces_warning(RuntimeWarning): - assert_series_equal(s_tft & s_0123, exp) - else: - exp = Series([False] * 7, index=[0, 1, 2, 3, 'a', 'b', 'c']) - assert_series_equal(s_tft & s_0123, exp) - - # s_tft will be all false now because of reindexing like s_0123 - if compat.PY3: - # unable to sort incompatible object via .union. - exp = Series([False] * 7, index=[0, 1, 2, 3, 'b', 'c', 'a']) - with tm.assert_produces_warning(RuntimeWarning): - assert_series_equal(s_0123 & s_tft, exp) - else: - exp = Series([False] * 7, index=[0, 1, 2, 3, 'a', 'b', 'c']) - assert_series_equal(s_0123 & s_tft, exp) - - assert_series_equal(s_0123 & False, Series([False] * 4)) - assert_series_equal(s_0123 ^ False, Series([False, True, True, True])) - assert_series_equal(s_0123 & [False], Series([False] * 4)) - assert_series_equal(s_0123 & (False), Series([False] * 4)) - assert_series_equal(s_0123 & Series([False, np.NaN, False, False]), - Series([False] * 4)) - - s_ftft = Series([False, True, False, True]) - assert_series_equal(s_0123 & Series([0.1, 4, -3.14, 2]), s_ftft) - - s_abNd = Series(['a', 'b', np.NaN, 'd']) - res = s_0123 & s_abNd - expected = s_ftft - assert_series_equal(res, expected) - - def test_scalar_na_cmp_corners(self): - s = Series([2, 3, 4, 5, 6, 7, 8, 9, 10]) - - with pytest.raises(TypeError): - s & datetime(2005, 1, 1) - - s = Series([2, 3, 4, 5, 6, 7, 8, 9, datetime(2005, 1, 1)]) - s[::2] = np.nan - - expected = Series(True, index=s.index) - expected[::2] = False - result = s & list(s) - assert_series_equal(result, expected) - - d = DataFrame({'A': s}) - # TODO: Fix this exception - needs to be fixed! (see GH5035) - # (previously this was a TypeError because series returned - # NotImplemented - - # this is an alignment issue; these are equivalent - # https://github.com/pandas-dev/pandas/issues/5284 - - with pytest.raises(TypeError): - d.__and__(s, axis='columns') - - with pytest.raises(TypeError): - s & d - - # this is wrong as its not a boolean result - # result = d.__and__(s,axis='index') - def test_operators_corner(self): series = self.ts @@ -934,62 +989,15 @@ def test_idxminmax_with_inf(self): np.isnan(s.idxmax(skipna=False)) -class TestSeriesOperationsDataFrameCompat(object): - - def test_bool_ops_df_compat(self): - # GH 1134 - s1 = pd.Series([True, False, True], index=list('ABC'), name='x') - s2 = pd.Series([True, True, False], index=list('ABD'), name='x') - - exp = pd.Series([True, False, False, False], - index=list('ABCD'), name='x') - assert_series_equal(s1 & s2, exp) - assert_series_equal(s2 & s1, exp) - - # True | np.nan => True - exp = pd.Series([True, True, True, False], - index=list('ABCD'), name='x') - assert_series_equal(s1 | s2, exp) - # np.nan | True => np.nan, filled with False - exp = pd.Series([True, True, False, False], - index=list('ABCD'), name='x') - assert_series_equal(s2 | s1, exp) - - # DataFrame doesn't fill nan with False - exp = pd.DataFrame({'x': [True, False, np.nan, np.nan]}, - index=list('ABCD')) - assert_frame_equal(s1.to_frame() & s2.to_frame(), exp) - assert_frame_equal(s2.to_frame() & s1.to_frame(), exp) - - exp = pd.DataFrame({'x': [True, True, np.nan, np.nan]}, - index=list('ABCD')) - assert_frame_equal(s1.to_frame() | s2.to_frame(), exp) - assert_frame_equal(s2.to_frame() | s1.to_frame(), exp) - - # different length - s3 = pd.Series([True, False, True], index=list('ABC'), name='x') - s4 = pd.Series([True, True, True, True], index=list('ABCD'), name='x') - - exp = pd.Series([True, False, True, False], - index=list('ABCD'), name='x') - assert_series_equal(s3 & s4, exp) - assert_series_equal(s4 & s3, exp) - - # np.nan | True => np.nan, filled with False - exp = pd.Series([True, True, True, False], - index=list('ABCD'), name='x') - assert_series_equal(s3 | s4, exp) - # True | np.nan => True - exp = pd.Series([True, True, True, True], - index=list('ABCD'), name='x') - assert_series_equal(s4 | s3, exp) +class TestSeriesUnaryOps(object): + # __neg__, __pos__, __inv__ - exp = pd.DataFrame({'x': [True, False, True, np.nan]}, - index=list('ABCD')) - assert_frame_equal(s3.to_frame() & s4.to_frame(), exp) - assert_frame_equal(s4.to_frame() & s3.to_frame(), exp) + def test_neg(self): + ser = tm.makeStringSeries() + ser.name = 'series' + assert_series_equal(-ser, -1 * ser) - exp = pd.DataFrame({'x': [True, True, True, np.nan]}, - index=list('ABCD')) - assert_frame_equal(s3.to_frame() | s4.to_frame(), exp) - assert_frame_equal(s4.to_frame() | s3.to_frame(), exp) + def test_invert(self): + ser = tm.makeStringSeries() + ser.name = 'series' + assert_series_equal(-(ser < 0), ~(ser < 0))