Skip to content

~Finish Collecting Arithmetic Tests #22350

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

Closed
wants to merge 10 commits into from
Closed
81 changes: 80 additions & 1 deletion pandas/tests/arithmetic/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,21 @@ def zero(request):

@pytest.fixture(params=[pd.Float64Index(np.arange(5, dtype='float64')),
pd.Int64Index(np.arange(5, dtype='int64')),
pd.UInt64Index(np.arange(5, dtype='uint64'))],
pd.UInt64Index(np.arange(5, dtype='uint64')),
pd.RangeIndex(5)],
ids=lambda x: type(x).__name__)
def idx(request):
return request.param


@pytest.fixture
def tdser():
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps td_series ? At least an underscore between td and ser would be good.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, will do.

"""
Return a Series with dtype='timedelta64[ns]', including a NaT.
"""
return pd.Series(['59 Days', '59 Days', 'NaT'], dtype='timedelta64[ns]')


@pytest.fixture(params=[pd.Timedelta('5m4s').to_pytimedelta(),
pd.Timedelta('5m4s'),
pd.Timedelta('5m4s').to_timedelta64()],
Expand All @@ -47,6 +56,76 @@ def scalar_td(request):
return request.param


# ------------------------------------------------------------------
# DateOffset Fixtures

_common_mismatch = [pd.offsets.YearBegin(2),
pd.offsets.MonthBegin(1),
pd.offsets.Minute()]


@pytest.fixture(params=[pd.Timedelta(minutes=30).to_pytimedelta(),
np.timedelta64(30, 's'),
pd.Timedelta(seconds=30)] + _common_mismatch)
def not_hourly(request):
Copy link
Contributor

Choose a reason for hiding this comment

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

I would add _fixture to these

Copy link
Contributor

Choose a reason for hiding this comment

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

can you do this

"""
Several timedelta-like and DateOffset instances that are _not_
compatible with Hourly frequencies.
"""
return request.param


@pytest.fixture(params=[np.timedelta64(4, 'h'),
pd.Timedelta(hours=23).to_pytimedelta(),
pd.Timedelta('23:00:00')] + _common_mismatch)
def not_daily(request):
"""
Several timedelta-like and DateOffset instances that are _not_
compatible with Daily frequencies.
"""
return request.param


@pytest.fixture(params=[np.timedelta64(365, 'D'),
pd.Timedelta(365).to_pytimedelta(),
pd.Timedelta(days=365)] + _common_mismatch)
def mismatched(request):
Copy link
Contributor

Choose a reason for hiding this comment

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

can you make this more descriptive

Copy link
Member Author

Choose a reason for hiding this comment

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

docstring doesn't get the job done?

Copy link
Contributor

Choose a reason for hiding this comment

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

no, prefer this to be a more descriptive name

"""
Several timedelta-like and DateOffset instances that are _not_
compatible with Monthly or Annual frequencies.
"""
return request.param


@pytest.fixture(params=[pd.offsets.Day(3),
pd.Timedelta(days=3).to_pytimedelta(),
np.timedelta64(3, 'D'),
pd.offsets.Hour(72),
pd.Timedelta(minutes=60 * 24 * 3).to_pytimedelta(),
np.timedelta64(72, 'h'),
pd.Timedelta('72:00:00')])
def three_days(request):
"""
Several timedelta-like and DateOffset objects that each represent
a 3-day timedelta
"""
return request.param


@pytest.fixture(params=[pd.offsets.Hour(2),
pd.Timedelta(hours=2),
np.timedelta64(2, 'h'),
pd.offsets.Minute(120),
pd.Timedelta(minutes=120).to_pytimedelta(),
np.timedelta64(120, 'm')])
def two_hours(request):
"""
Several timedelta-like and DateOffset objects that each represent
a 2-hour timedelta
"""
return request.param


# ------------------------------------------------------------------

@pytest.fixture(params=[pd.Index, pd.Series, pd.DataFrame],
Expand Down
32 changes: 12 additions & 20 deletions pandas/tests/arithmetic/test_datetime64.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@
# ------------------------------------------------------------------
# Fixtures

@pytest.fixture(params=[pd.offsets.Hour(2), timedelta(hours=2),
np.timedelta64(2, 'h'), Timedelta(hours=2)],
ids=str)
def delta(request):
# Several ways of representing two hours
return request.param


@pytest.fixture(
params=[
datetime(2011, 1, 1),
Expand Down Expand Up @@ -1113,40 +1105,40 @@ def test_dti_add_intarray_no_freq(self, box):
# -------------------------------------------------------------
# Binary operations DatetimeIndex and timedelta-like

def test_dti_add_timedeltalike(self, tz_naive_fixture, delta, box):
def test_dti_add_timedeltalike(self, tz_naive_fixture, two_hours, box):
# GH#22005, GH#22163 check DataFrame doesn't raise TypeError
tz = tz_naive_fixture
rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz)
rng = tm.box_expected(rng, box)

result = rng + delta
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)
tm.assert_equal(result, expected)

def test_dti_iadd_timedeltalike(self, tz_naive_fixture, delta):
def test_dti_iadd_timedeltalike(self, tz_naive_fixture, two_hours):
tz = tz_naive_fixture
rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz)
expected = pd.date_range('2000-01-01 02:00',
'2000-02-01 02:00', tz=tz)
rng += delta
rng += two_hours
tm.assert_index_equal(rng, expected)

def test_dti_sub_timedeltalike(self, tz_naive_fixture, delta):
def test_dti_sub_timedeltalike(self, tz_naive_fixture, two_hours):
tz = tz_naive_fixture
rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz)
expected = pd.date_range('1999-12-31 22:00',
'2000-01-31 22:00', tz=tz)
result = rng - delta
result = rng - two_hours
tm.assert_index_equal(result, expected)

def test_dti_isub_timedeltalike(self, tz_naive_fixture, delta):
def test_dti_isub_timedeltalike(self, tz_naive_fixture, two_hours):
tz = tz_naive_fixture
rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz)
expected = pd.date_range('1999-12-31 22:00',
'2000-01-31 22:00', tz=tz)
rng -= delta
rng -= two_hours
tm.assert_index_equal(rng, expected)

# -------------------------------------------------------------
Expand Down Expand Up @@ -1255,8 +1247,8 @@ def test_dti_isub_tdi(self, tz_naive_fixture):
def test_add_datetimelike_and_dti(self, addend):
# GH#9631
dti = DatetimeIndex(['2011-01-01', '2011-01-02'])
msg = 'cannot add DatetimeIndex and {0}'.format(
type(addend).__name__)
msg = ('cannot add DatetimeIndex and {typ}'
.format(typ=type(addend).__name__))
with tm.assert_raises_regex(TypeError, msg):
dti + addend
with tm.assert_raises_regex(TypeError, msg):
Expand All @@ -1266,8 +1258,8 @@ def test_add_datetimelike_and_dti_tz(self, addend):
# GH#9631
dti_tz = DatetimeIndex(['2011-01-01',
'2011-01-02']).tz_localize('US/Eastern')
msg = 'cannot add DatetimeIndex and {0}'.format(
type(addend).__name__)
msg = ('cannot add DatetimeIndex and {typ}'
.format(typ=type(addend).__name__))
with tm.assert_raises_regex(TypeError, msg):
dti_tz + addend
with tm.assert_raises_regex(TypeError, msg):
Expand Down
78 changes: 69 additions & 9 deletions pandas/tests/arithmetic/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@
from pandas import Timedelta, Series, Index, TimedeltaIndex


@pytest.fixture(params=[pd.Float64Index(np.arange(5, dtype='float64')),
pd.UInt64Index(np.arange(5, dtype='uint64')),
pd.Int64Index(np.arange(5, dtype='int64')),
pd.RangeIndex(5)],
ids=lambda x: type(x).__name__)
def idx(request):
return request.param


# ------------------------------------------------------------------
# Comparisons

Expand All @@ -43,6 +34,30 @@ def test_operator_series_comparison_zerorank(self):
expected = 0.0 > pd.Series([1, 2, 3])
tm.assert_series_equal(result, expected)

def test_df_numeric_cmp_dt64_raises(self):
# GH#8932, GH#22163
ts = pd.Timestamp.now()
df = pd.DataFrame({'x': range(5)})
with pytest.raises(TypeError):
df > ts
Copy link
Contributor

Choose a reason for hiding this comment

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

commented in another PR these should be in test_datetime

with pytest.raises(TypeError):
df < ts
with pytest.raises(TypeError):
ts < df
with pytest.raises(TypeError):
ts > df

assert not (df == ts).any().any()
assert (df != ts).all().all()

def test_compare_invalid(self):
# GH#8058
# ops testing
a = pd.Series(np.random.randn(5), name=0)
b = pd.Series(np.random.randn(5))
b.name = pd.Timestamp('2000-01-01')
tm.assert_series_equal(a / b, 1 / (b / a))


# ------------------------------------------------------------------
# Numeric dtypes Arithmetic with Timedelta Scalar
Expand Down Expand Up @@ -712,6 +727,51 @@ def check(series, other):
check(tser, 5)


class TestUFuncCompat(object):
Copy link
Contributor

Choose a reason for hiding this comment

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

let's think about putting these in a separate file (test_funcs)? (may want to make numeric a subdir, its already getting long).

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll give that some thought. Preference is to do quick turnarounds with small PRs here since there are lots of bugs to fix.

@pytest.mark.parametrize('holder', [pd.Int64Index, pd.UInt64Index,
pd.Float64Index, pd.Series])
def test_ufunc_coercions(self, holder):
idx = holder([1, 2, 3, 4, 5], name='x')
box = pd.Series if holder is pd.Series else pd.Index

result = np.sqrt(idx)
assert result.dtype == 'f8' and isinstance(result, box)
exp = pd.Float64Index(np.sqrt(np.array([1, 2, 3, 4, 5])), name='x')
exp = tm.box_expected(exp, box)
tm.assert_equal(result, exp)

result = np.divide(idx, 2.)
assert result.dtype == 'f8' and isinstance(result, box)
exp = pd.Float64Index([0.5, 1., 1.5, 2., 2.5], name='x')
exp = tm.box_expected(exp, box)
tm.assert_equal(result, exp)

# _evaluate_numeric_binop
result = idx + 2.
assert result.dtype == 'f8' and isinstance(result, box)
exp = pd.Float64Index([3., 4., 5., 6., 7.], name='x')
exp = tm.box_expected(exp, box)
tm.assert_equal(result, exp)

result = idx - 2.
assert result.dtype == 'f8' and isinstance(result, box)
exp = pd.Float64Index([-1., 0., 1., 2., 3.], name='x')
exp = tm.box_expected(exp, box)
tm.assert_equal(result, exp)

result = idx * 1.
assert result.dtype == 'f8' and isinstance(result, box)
exp = pd.Float64Index([1., 2., 3., 4., 5.], name='x')
exp = tm.box_expected(exp, box)
tm.assert_equal(result, exp)

result = idx / 2.
assert result.dtype == 'f8' and isinstance(result, box)
exp = pd.Float64Index([0.5, 1., 1.5, 2., 2.5], name='x')
exp = tm.box_expected(exp, box)
tm.assert_equal(result, exp)


class TestObjectDtypeEquivalence(object):
# Tests that arithmetic operations match operations executed elementwise

Expand Down
33 changes: 33 additions & 0 deletions pandas/tests/arithmetic/test_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,36 @@ def test_series_with_dtype_radd_timedelta(self, dtype):

result = ser + pd.Timedelta('3 days')
tm.assert_series_equal(result, expected)

# TODO: cleanup & parametrize over box
def test_mixed_timezone_series_ops_object(self):
# GH#13043
s = pd.Series([pd.Timestamp('2015-01-01', tz='US/Eastern'),
pd.Timestamp('2015-01-01', tz='Asia/Tokyo')],
name='xxx')
assert s.dtype == object

exp = pd.Series([pd.Timestamp('2015-01-02', tz='US/Eastern'),
pd.Timestamp('2015-01-02', tz='Asia/Tokyo')],
name='xxx')
tm.assert_series_equal(s + pd.Timedelta('1 days'), exp)
tm.assert_series_equal(pd.Timedelta('1 days') + s, exp)

# object series & object series
s2 = pd.Series([pd.Timestamp('2015-01-03', tz='US/Eastern'),
pd.Timestamp('2015-01-05', tz='Asia/Tokyo')],
name='xxx')
assert s2.dtype == object
exp = pd.Series([pd.Timedelta('2 days'), pd.Timedelta('4 days')],
name='xxx')
tm.assert_series_equal(s2 - s, exp)
tm.assert_series_equal(s - s2, -exp)

s = pd.Series([pd.Timedelta('01:00:00'), pd.Timedelta('02:00:00')],
name='xxx', dtype=object)
assert s.dtype == object

exp = pd.Series([pd.Timedelta('01:30:00'), pd.Timedelta('02:30:00')],
name='xxx')
tm.assert_series_equal(s + pd.Timedelta('00:30:00'), exp)
tm.assert_series_equal(pd.Timedelta('00:30:00') + s, exp)
Loading