Skip to content

Commit b36e06c

Browse files
jbrockmendeljreback
authored andcommitted
REF/TST: Collect Straggler Arithmetic Tests (pandas-dev#24376)
1 parent a70694e commit b36e06c

12 files changed

+756
-733
lines changed

pandas/tests/arithmetic/test_datetime64.py

+120
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from pandas._libs.tslibs.conversion import localize_pydatetime
2121
from pandas._libs.tslibs.offsets import shift_months
2222

23+
from pandas.core.indexes.datetimes import _to_m8
24+
2325
from pandas import (
2426
Timestamp, Timedelta, Period, Series, date_range, NaT,
2527
DatetimeIndex, TimedeltaIndex)
@@ -61,6 +63,50 @@ def test_dt64_nat_comparison(self):
6163

6264
class TestDatetime64SeriesComparison(object):
6365
# TODO: moved from tests.series.test_operators; needs cleanup
66+
67+
@pytest.mark.parametrize('pair', [
68+
([pd.Timestamp('2011-01-01'), NaT, pd.Timestamp('2011-01-03')],
69+
[NaT, NaT, pd.Timestamp('2011-01-03')]),
70+
71+
([pd.Timedelta('1 days'), NaT, pd.Timedelta('3 days')],
72+
[NaT, NaT, pd.Timedelta('3 days')]),
73+
74+
([pd.Period('2011-01', freq='M'), NaT,
75+
pd.Period('2011-03', freq='M')],
76+
[NaT, NaT, pd.Period('2011-03', freq='M')]),
77+
78+
])
79+
@pytest.mark.parametrize('reverse', [True, False])
80+
@pytest.mark.parametrize('box', [Series, pd.Index])
81+
@pytest.mark.parametrize('dtype', [None, object])
82+
def test_nat_comparisons(self, dtype, box, reverse, pair):
83+
l, r = pair
84+
if reverse:
85+
# add lhs / rhs switched data
86+
l, r = r, l
87+
88+
left = Series(l, dtype=dtype)
89+
right = box(r, dtype=dtype)
90+
# Series, Index
91+
92+
expected = Series([False, False, True])
93+
tm.assert_series_equal(left == right, expected)
94+
95+
expected = Series([True, True, False])
96+
tm.assert_series_equal(left != right, expected)
97+
98+
expected = Series([False, False, False])
99+
tm.assert_series_equal(left < right, expected)
100+
101+
expected = Series([False, False, False])
102+
tm.assert_series_equal(left > right, expected)
103+
104+
expected = Series([False, False, True])
105+
tm.assert_series_equal(left >= right, expected)
106+
107+
expected = Series([False, False, True])
108+
tm.assert_series_equal(left <= right, expected)
109+
64110
def test_comparison_invalid(self, box_with_array):
65111
# GH#4968
66112
# invalid date/int comparisons
@@ -272,8 +318,46 @@ def test_dt64arr_timestamp_equality(self, box_with_array):
272318
expected = tm.box_expected([False, False], xbox)
273319
tm.assert_equal(result, expected)
274320

321+
@pytest.mark.parametrize('op', [operator.eq, operator.ne,
322+
operator.gt, operator.ge,
323+
operator.lt, operator.le])
324+
def test_comparison_tzawareness_compat(self, op):
325+
# GH#18162
326+
dr = pd.date_range('2016-01-01', periods=6)
327+
dz = dr.tz_localize('US/Pacific')
328+
329+
# Check that there isn't a problem aware-aware and naive-naive do not
330+
# raise
331+
naive_series = Series(dr)
332+
aware_series = Series(dz)
333+
with pytest.raises(TypeError):
334+
op(dz, naive_series)
335+
with pytest.raises(TypeError):
336+
op(dr, aware_series)
337+
338+
# TODO: implement _assert_tzawareness_compat for the reverse
339+
# comparison with the Series on the left-hand side
340+
275341

276342
class TestDatetimeIndexComparisons(object):
343+
344+
# TODO: moved from tests.indexes.test_base; parametrize and de-duplicate
345+
@pytest.mark.parametrize("op", [
346+
operator.eq, operator.ne, operator.gt, operator.lt,
347+
operator.ge, operator.le
348+
])
349+
def test_comparators(self, op):
350+
index = tm.makeDateIndex(100)
351+
element = index[len(index) // 2]
352+
element = _to_m8(element)
353+
354+
arr = np.array(index)
355+
arr_result = op(arr, element)
356+
index_result = op(index, element)
357+
358+
assert isinstance(index_result, np.ndarray)
359+
tm.assert_numpy_array_equal(arr_result, index_result)
360+
277361
@pytest.mark.parametrize('other', [datetime(2016, 1, 1),
278362
Timestamp('2016-01-01'),
279363
np.datetime64('2016-01-01')])
@@ -1450,6 +1534,42 @@ def test_datetimeindex_sub_datetimeindex_overflow(self):
14501534

14511535
class TestTimestampSeriesArithmetic(object):
14521536

1537+
def test_empty_series_add_sub(self):
1538+
# GH#13844
1539+
a = Series(dtype='M8[ns]')
1540+
b = Series(dtype='m8[ns]')
1541+
tm.assert_series_equal(a, a + b)
1542+
tm.assert_series_equal(a, a - b)
1543+
tm.assert_series_equal(a, b + a)
1544+
with pytest.raises(TypeError):
1545+
b - a
1546+
1547+
def test_operators_datetimelike(self):
1548+
1549+
# ## timedelta64 ###
1550+
td1 = Series([timedelta(minutes=5, seconds=3)] * 3)
1551+
td1.iloc[2] = np.nan
1552+
1553+
# ## datetime64 ###
1554+
dt1 = Series([pd.Timestamp('20111230'), pd.Timestamp('20120101'),
1555+
pd.Timestamp('20120103')])
1556+
dt1.iloc[2] = np.nan
1557+
dt2 = Series([pd.Timestamp('20111231'), pd.Timestamp('20120102'),
1558+
pd.Timestamp('20120104')])
1559+
dt1 - dt2
1560+
dt2 - dt1
1561+
1562+
# ## datetime64 with timetimedelta ###
1563+
dt1 + td1
1564+
td1 + dt1
1565+
dt1 - td1
1566+
# TODO: Decide if this ought to work.
1567+
# td1 - dt1
1568+
1569+
# ## timetimedelta with datetime64 ###
1570+
td1 + dt1
1571+
dt1 + td1
1572+
14531573
def test_dt64ser_sub_datetime_dtype(self):
14541574
ts = Timestamp(datetime(1993, 1, 7, 13, 30, 00))
14551575
dt = datetime(1993, 6, 22, 13, 30)

pandas/tests/arithmetic/test_numeric.py

+121-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# behave identically.
44
# Specifically for numeric dtypes
55
from decimal import Decimal
6+
from itertools import combinations
67
import operator
78

89
import pytest
@@ -846,11 +847,15 @@ def check(series, other):
846847
class TestUFuncCompat(object):
847848

848849
@pytest.mark.parametrize('holder', [pd.Int64Index, pd.UInt64Index,
849-
pd.Float64Index, pd.Series])
850+
pd.Float64Index, pd.RangeIndex,
851+
pd.Series])
850852
def test_ufunc_compat(self, holder):
851853
box = pd.Series if holder is pd.Series else pd.Index
852854

853-
idx = holder(np.arange(5, dtype='int64'))
855+
if holder is pd.RangeIndex:
856+
idx = pd.RangeIndex(0, 5)
857+
else:
858+
idx = holder(np.arange(5, dtype='int64'))
854859
result = np.sin(idx)
855860
expected = box(np.sin(np.arange(5, dtype='int64')))
856861
tm.assert_equal(result, expected)
@@ -940,3 +945,117 @@ def test_operators_reverse_object(self, op):
940945
result = op(1., arr)
941946
expected = op(1., arr.astype(float))
942947
tm.assert_series_equal(result.astype(float), expected)
948+
949+
950+
class TestNumericArithmeticUnsorted(object):
951+
# Tests in this class have been moved from type-specific test modules
952+
# but not yet sorted, parametrized, and de-duplicated
953+
954+
def check_binop(self, ops, scalars, idxs):
955+
for op in ops:
956+
for a, b in combinations(idxs, 2):
957+
result = op(a, b)
958+
expected = op(pd.Int64Index(a), pd.Int64Index(b))
959+
tm.assert_index_equal(result, expected)
960+
for idx in idxs:
961+
for scalar in scalars:
962+
result = op(idx, scalar)
963+
expected = op(pd.Int64Index(idx), scalar)
964+
tm.assert_index_equal(result, expected)
965+
966+
def test_binops(self):
967+
ops = [operator.add, operator.sub, operator.mul, operator.floordiv,
968+
operator.truediv]
969+
scalars = [-1, 1, 2]
970+
idxs = [pd.RangeIndex(0, 10, 1), pd.RangeIndex(0, 20, 2),
971+
pd.RangeIndex(-10, 10, 2), pd.RangeIndex(5, -5, -1)]
972+
self.check_binop(ops, scalars, idxs)
973+
974+
def test_binops_pow(self):
975+
# later versions of numpy don't allow powers of negative integers
976+
# so test separately
977+
# https://github.com/numpy/numpy/pull/8127
978+
ops = [pow]
979+
scalars = [1, 2]
980+
idxs = [pd.RangeIndex(0, 10, 1), pd.RangeIndex(0, 20, 2)]
981+
self.check_binop(ops, scalars, idxs)
982+
983+
# TODO: mod, divmod?
984+
@pytest.mark.parametrize('op', [operator.add, operator.sub,
985+
operator.mul, operator.floordiv,
986+
operator.truediv, operator.pow])
987+
def test_arithmetic_with_frame_or_series(self, op):
988+
# check that we return NotImplemented when operating with Series
989+
# or DataFrame
990+
index = pd.RangeIndex(5)
991+
other = pd.Series(np.random.randn(5))
992+
993+
expected = op(pd.Series(index), other)
994+
result = op(index, other)
995+
tm.assert_series_equal(result, expected)
996+
997+
other = pd.DataFrame(np.random.randn(2, 5))
998+
expected = op(pd.DataFrame([index, index]), other)
999+
result = op(index, other)
1000+
tm.assert_frame_equal(result, expected)
1001+
1002+
def test_numeric_compat2(self):
1003+
# validate that we are handling the RangeIndex overrides to numeric ops
1004+
# and returning RangeIndex where possible
1005+
1006+
idx = pd.RangeIndex(0, 10, 2)
1007+
1008+
result = idx * 2
1009+
expected = pd.RangeIndex(0, 20, 4)
1010+
tm.assert_index_equal(result, expected, exact=True)
1011+
1012+
result = idx + 2
1013+
expected = pd.RangeIndex(2, 12, 2)
1014+
tm.assert_index_equal(result, expected, exact=True)
1015+
1016+
result = idx - 2
1017+
expected = pd.RangeIndex(-2, 8, 2)
1018+
tm.assert_index_equal(result, expected, exact=True)
1019+
1020+
# truediv under PY3
1021+
result = idx / 2
1022+
1023+
if PY3:
1024+
expected = pd.RangeIndex(0, 5, 1).astype('float64')
1025+
else:
1026+
expected = pd.RangeIndex(0, 5, 1)
1027+
tm.assert_index_equal(result, expected, exact=True)
1028+
1029+
result = idx / 4
1030+
expected = pd.RangeIndex(0, 10, 2) / 4
1031+
tm.assert_index_equal(result, expected, exact=True)
1032+
1033+
result = idx // 1
1034+
expected = idx
1035+
tm.assert_index_equal(result, expected, exact=True)
1036+
1037+
# __mul__
1038+
result = idx * idx
1039+
expected = Index(idx.values * idx.values)
1040+
tm.assert_index_equal(result, expected, exact=True)
1041+
1042+
# __pow__
1043+
idx = pd.RangeIndex(0, 1000, 2)
1044+
result = idx ** 2
1045+
expected = idx._int64index ** 2
1046+
tm.assert_index_equal(Index(result.values), expected, exact=True)
1047+
1048+
# __floordiv__
1049+
cases_exact = [
1050+
(pd.RangeIndex(0, 1000, 2), 2, pd.RangeIndex(0, 500, 1)),
1051+
(pd.RangeIndex(-99, -201, -3), -3, pd.RangeIndex(33, 67, 1)),
1052+
(pd.RangeIndex(0, 1000, 1), 2,
1053+
pd.RangeIndex(0, 1000, 1)._int64index // 2),
1054+
(pd.RangeIndex(0, 100, 1), 2.0,
1055+
pd.RangeIndex(0, 100, 1)._int64index // 2.0),
1056+
(pd.RangeIndex(0), 50, pd.RangeIndex(0)),
1057+
(pd.RangeIndex(2, 4, 2), 3, pd.RangeIndex(0, 1, 1)),
1058+
(pd.RangeIndex(-5, -10, -6), 4, pd.RangeIndex(-2, -1, 1)),
1059+
(pd.RangeIndex(-100, -200, 3), 2, pd.RangeIndex(0))]
1060+
for idx, div, expected in cases_exact:
1061+
tm.assert_index_equal(idx // div, expected, exact=True)

pandas/tests/arithmetic/test_object.py

+15
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,21 @@ def test_more_na_comparisons(self, dtype):
7373

7474
class TestArithmetic(object):
7575

76+
# TODO: parametrize
77+
def test_pow_ops_object(self):
78+
# GH#22922
79+
# pow is weird with masking & 1, so testing here
80+
a = Series([1, np.nan, 1, np.nan], dtype=object)
81+
b = Series([1, np.nan, np.nan, 1], dtype=object)
82+
result = a ** b
83+
expected = Series(a.values ** b.values, dtype=object)
84+
tm.assert_series_equal(result, expected)
85+
86+
result = b ** a
87+
expected = Series(b.values ** a.values, dtype=object)
88+
89+
tm.assert_series_equal(result, expected)
90+
7691
@pytest.mark.parametrize("op", [operator.add, ops.radd])
7792
@pytest.mark.parametrize("other", ["category", "Int64"])
7893
def test_add_extension_scalar(self, other, box, op):

0 commit comments

Comments
 (0)