Skip to content

Collect datetime64 and PeriodDtype arithmetic tests #22237

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

Merged
merged 7 commits into from
Aug 8, 2018
Merged
Changes from all commits
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
Empty file.
39 changes: 39 additions & 0 deletions pandas/tests/arithmetic/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
import pytest

import numpy as np
import pandas as pd


@pytest.fixture(params=[1, np.array(1, dtype=np.int64)])
def one(request):
# zero-dim integer array behaves like an integer
return request.param


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

@pytest.fixture(params=[pd.Index, pd.Series, pd.DataFrame],
ids=lambda x: x.__name__)
def box(request):
"""
Several array-like containers that should have effectively identical
behavior with respect to arithmetic operations.
"""
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.
"""
return request.param
1,386 changes: 1,386 additions & 0 deletions pandas/tests/arithmetic/test_datetime64.py

Large diffs are not rendered by default.

1,057 changes: 1,057 additions & 0 deletions pandas/tests/arithmetic/test_period.py

Large diffs are not rendered by default.

52 changes: 0 additions & 52 deletions pandas/tests/frame/test_arithmetic.py
Original file line number Diff line number Diff line change
@@ -59,15 +59,6 @@ def test_df_flex_cmp_constant_return_types_empty(self, opname):
result = getattr(empty, opname)(const).get_dtype_counts()
tm.assert_series_equal(result, pd.Series([2], ['bool']))

@pytest.mark.parametrize('timestamps', [
[pd.Timestamp('2012-01-01 13:00:00+00:00')] * 2,
[pd.Timestamp('2012-01-01 13:00:00')] * 2])
def test_tz_aware_scalar_comparison(self, timestamps):
# Test for issue #15966
df = pd.DataFrame({'test': timestamps})
expected = pd.DataFrame({'test': [False, False]})
tm.assert_frame_equal(df == -1, expected)


# -------------------------------------------------------------------
# Arithmetic
@@ -91,17 +82,6 @@ def test_df_add_flex_filled_mixed_dtypes(self):

class TestFrameArithmetic(object):

@pytest.mark.xfail(reason='GH#7996 datetime64 units not converted to nano',
strict=True)
def test_df_sub_datetime64_not_ns(self):
df = pd.DataFrame(pd.date_range('20130101', periods=3))
dt64 = np.datetime64('2013-01-01')
assert dt64.dtype == 'datetime64[D]'
res = df - dt64
expected = pd.DataFrame([pd.Timedelta(days=0), pd.Timedelta(days=1),
pd.Timedelta(days=2)])
tm.assert_frame_equal(res, expected)

@pytest.mark.parametrize('data', [
[1, 2, 3],
[1.1, 2.2, 3.3],
@@ -135,35 +115,3 @@ def test_df_radd_str(self):
df = pd.DataFrame(['x', np.nan, 'x'])
tm.assert_frame_equal('a' + df, pd.DataFrame(['ax', np.nan, 'ax']))
tm.assert_frame_equal(df + 'a', pd.DataFrame(['xa', np.nan, 'xa']))


class TestPeriodFrameArithmetic(object):

def test_ops_frame_period(self):
# GH 13043
df = pd.DataFrame({'A': [pd.Period('2015-01', freq='M'),
pd.Period('2015-02', freq='M')],
'B': [pd.Period('2014-01', freq='M'),
pd.Period('2014-02', freq='M')]})
assert df['A'].dtype == object
assert df['B'].dtype == object

p = pd.Period('2015-03', freq='M')
off = p.freq
# dtype will be object because of original dtype
exp = pd.DataFrame({'A': np.array([2 * off, 1 * off], dtype=object),
'B': np.array([14 * off, 13 * off], dtype=object)})
tm.assert_frame_equal(p - df, exp)
tm.assert_frame_equal(df - p, -1 * exp)

df2 = pd.DataFrame({'A': [pd.Period('2015-05', freq='M'),
pd.Period('2015-06', freq='M')],
'B': [pd.Period('2015-05', freq='M'),
pd.Period('2015-06', freq='M')]})
assert df2['A'].dtype == object
assert df2['B'].dtype == object

exp = pd.DataFrame({'A': np.array([4 * off, 4 * off], dtype=object),
'B': np.array([16 * off, 16 * off], dtype=object)})
tm.assert_frame_equal(df2 - df, exp)
tm.assert_frame_equal(df - df2, -1 * exp)
1,168 changes: 3 additions & 1,165 deletions pandas/tests/indexes/datetimes/test_arithmetic.py

Large diffs are not rendered by default.

845 changes: 1 addition & 844 deletions pandas/tests/indexes/period/test_arithmetic.py

Large diffs are not rendered by default.

300 changes: 2 additions & 298 deletions pandas/tests/series/test_arithmetic.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
from datetime import timedelta
import operator
from decimal import Decimal

import numpy as np
import pytest

from pandas import Series, Timestamp, Period
from pandas._libs.tslibs.period import IncompatibleFrequency
from pandas import Series, Timestamp

import pandas as pd
import pandas.util.testing as tm
@@ -79,132 +78,6 @@ def test_ser_cmp_result_names(self, names, op):
assert result.name == names[2]


class TestTimestampSeriesComparison(object):
def test_dt64_ser_cmp_date_warning(self):
# https://github.com/pandas-dev/pandas/issues/21359
# Remove this test and enble invalid test below
ser = pd.Series(pd.date_range('20010101', periods=10), name='dates')
date = ser.iloc[0].to_pydatetime().date()

with tm.assert_produces_warning(FutureWarning) as m:
result = ser == date
expected = pd.Series([True] + [False] * 9, name='dates')
tm.assert_series_equal(result, expected)
assert "Comparing Series of datetimes " in str(m[0].message)
assert "will not compare equal" in str(m[0].message)

with tm.assert_produces_warning(FutureWarning) as m:
result = ser != date
tm.assert_series_equal(result, ~expected)
assert "will not compare equal" in str(m[0].message)

with tm.assert_produces_warning(FutureWarning) as m:
result = ser <= date
tm.assert_series_equal(result, expected)
assert "a TypeError will be raised" in str(m[0].message)

with tm.assert_produces_warning(FutureWarning) as m:
result = ser < date
tm.assert_series_equal(result, pd.Series([False] * 10, name='dates'))
assert "a TypeError will be raised" in str(m[0].message)

with tm.assert_produces_warning(FutureWarning) as m:
result = ser >= date
tm.assert_series_equal(result, pd.Series([True] * 10, name='dates'))
assert "a TypeError will be raised" in str(m[0].message)

with tm.assert_produces_warning(FutureWarning) as m:
result = ser > date
tm.assert_series_equal(result, pd.Series([False] + [True] * 9,
name='dates'))
assert "a TypeError will be raised" in str(m[0].message)

@pytest.mark.skip(reason="GH-21359")
def test_dt64ser_cmp_date_invalid(self):
# GH#19800 datetime.date comparison raises to
# match DatetimeIndex/Timestamp. This also matches the behavior
# of stdlib datetime.datetime
ser = pd.Series(pd.date_range('20010101', periods=10), name='dates')
date = ser.iloc[0].to_pydatetime().date()
assert not (ser == date).any()
assert (ser != date).all()
with pytest.raises(TypeError):
ser > date
with pytest.raises(TypeError):
ser < date
with pytest.raises(TypeError):
ser >= date
with pytest.raises(TypeError):
ser <= date

def test_dt64ser_cmp_period_scalar(self):
ser = Series(pd.period_range('2000-01-01', periods=10, freq='D'))
val = Period('2000-01-04', freq='D')
result = ser > val
expected = Series([x > val for x in ser])
tm.assert_series_equal(result, expected)

val = ser[5]
result = ser > val
expected = Series([x > val for x in ser])
tm.assert_series_equal(result, expected)

@pytest.mark.parametrize("left,right", [
("lt", "gt"),
("le", "ge"),
("eq", "eq"),
("ne", "ne"),
])
def test_timestamp_compare_series(self, left, right):
# see gh-4982
# Make sure we can compare Timestamps on the right AND left hand side.
ser = pd.Series(pd.date_range("20010101", periods=10), name="dates")
s_nat = ser.copy(deep=True)

ser[0] = pd.Timestamp("nat")
ser[3] = pd.Timestamp("nat")

left_f = getattr(operator, left)
right_f = getattr(operator, right)

# No NaT
expected = left_f(ser, pd.Timestamp("20010109"))
result = right_f(pd.Timestamp("20010109"), ser)
tm.assert_series_equal(result, expected)

# NaT
expected = left_f(ser, pd.Timestamp("nat"))
result = right_f(pd.Timestamp("nat"), ser)
tm.assert_series_equal(result, expected)

# Compare to Timestamp with series containing NaT
expected = left_f(s_nat, pd.Timestamp("20010109"))
result = right_f(pd.Timestamp("20010109"), s_nat)
tm.assert_series_equal(result, expected)

# Compare to NaT with series containing NaT
expected = left_f(s_nat, pd.Timestamp("nat"))
result = right_f(pd.Timestamp("nat"), s_nat)
tm.assert_series_equal(result, expected)

def test_timestamp_equality(self):
# GH#11034
ser = pd.Series([pd.Timestamp('2000-01-29 01:59:00'), 'NaT'])
result = ser != ser
tm.assert_series_equal(result, pd.Series([False, True]))
result = ser != ser[0]
tm.assert_series_equal(result, pd.Series([False, True]))
result = ser != ser[1]
tm.assert_series_equal(result, pd.Series([True, True]))

result = ser == ser
tm.assert_series_equal(result, pd.Series([True, False]))
result = ser == ser[0]
tm.assert_series_equal(result, pd.Series([True, False]))
result = ser == ser[1]
tm.assert_series_equal(result, pd.Series([False, False]))


class TestTimedeltaSeriesComparisons(object):
def test_compare_timedelta_series(self):
# regresssion test for GH5963
@@ -214,112 +87,6 @@ def test_compare_timedelta_series(self):
tm.assert_series_equal(actual, expected)


class TestPeriodSeriesComparisons(object):
@pytest.mark.parametrize('freq', ['M', '2M', '3M'])
def test_cmp_series_period_scalar(self, freq):
# GH 13200
base = Series([Period(x, freq=freq) for x in
['2011-01', '2011-02', '2011-03', '2011-04']])
p = Period('2011-02', freq=freq)

exp = Series([False, True, False, False])
tm.assert_series_equal(base == p, exp)
tm.assert_series_equal(p == base, exp)

exp = Series([True, False, True, True])
tm.assert_series_equal(base != p, exp)
tm.assert_series_equal(p != base, exp)

exp = Series([False, False, True, True])
tm.assert_series_equal(base > p, exp)
tm.assert_series_equal(p < base, exp)

exp = Series([True, False, False, False])
tm.assert_series_equal(base < p, exp)
tm.assert_series_equal(p > base, exp)

exp = Series([False, True, True, True])
tm.assert_series_equal(base >= p, exp)
tm.assert_series_equal(p <= base, exp)

exp = Series([True, True, False, False])
tm.assert_series_equal(base <= p, exp)
tm.assert_series_equal(p >= base, exp)

# different base freq
msg = "Input has different freq=A-DEC from Period"
with tm.assert_raises_regex(IncompatibleFrequency, msg):
base <= Period('2011', freq='A')

with tm.assert_raises_regex(IncompatibleFrequency, msg):
Period('2011', freq='A') >= base

@pytest.mark.parametrize('freq', ['M', '2M', '3M'])
def test_cmp_series_period_series(self, freq):
# GH#13200
base = Series([Period(x, freq=freq) for x in
['2011-01', '2011-02', '2011-03', '2011-04']])

ser = Series([Period(x, freq=freq) for x in
['2011-02', '2011-01', '2011-03', '2011-05']])

exp = Series([False, False, True, False])
tm.assert_series_equal(base == ser, exp)

exp = Series([True, True, False, True])
tm.assert_series_equal(base != ser, exp)

exp = Series([False, True, False, False])
tm.assert_series_equal(base > ser, exp)

exp = Series([True, False, False, True])
tm.assert_series_equal(base < ser, exp)

exp = Series([False, True, True, False])
tm.assert_series_equal(base >= ser, exp)

exp = Series([True, False, True, True])
tm.assert_series_equal(base <= ser, exp)

ser2 = Series([Period(x, freq='A') for x in
['2011', '2011', '2011', '2011']])

# different base freq
msg = "Input has different freq=A-DEC from Period"
with tm.assert_raises_regex(IncompatibleFrequency, msg):
base <= ser2

def test_cmp_series_period_series_mixed_freq(self):
# GH#13200
base = Series([Period('2011', freq='A'),
Period('2011-02', freq='M'),
Period('2013', freq='A'),
Period('2011-04', freq='M')])

ser = Series([Period('2012', freq='A'),
Period('2011-01', freq='M'),
Period('2013', freq='A'),
Period('2011-05', freq='M')])

exp = Series([False, False, True, False])
tm.assert_series_equal(base == ser, exp)

exp = Series([True, True, False, True])
tm.assert_series_equal(base != ser, exp)

exp = Series([False, True, False, False])
tm.assert_series_equal(base > ser, exp)

exp = Series([True, False, False, True])
tm.assert_series_equal(base < ser, exp)

exp = Series([False, True, True, False])
tm.assert_series_equal(base >= ser, exp)

exp = Series([True, False, True, True])
tm.assert_series_equal(base <= ser, exp)


# ------------------------------------------------------------------
# Arithmetic

@@ -423,66 +190,3 @@ def test_series_with_dtype_radd_timedelta(self, dtype):

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


class TestPeriodSeriesArithmetic(object):
def test_ops_series_timedelta(self):
# GH 13043
ser = pd.Series([pd.Period('2015-01-01', freq='D'),
pd.Period('2015-01-02', freq='D')], name='xxx')
assert ser.dtype == object

expected = pd.Series([pd.Period('2015-01-02', freq='D'),
pd.Period('2015-01-03', freq='D')], name='xxx')

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

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

result = ser + pd.tseries.offsets.Day()
tm.assert_series_equal(result, expected)

result = pd.tseries.offsets.Day() + ser
tm.assert_series_equal(result, expected)

def test_ops_series_period(self):
# GH 13043
ser = pd.Series([pd.Period('2015-01-01', freq='D'),
pd.Period('2015-01-02', freq='D')], name='xxx')
assert ser.dtype == object

per = pd.Period('2015-01-10', freq='D')
off = per.freq
# dtype will be object because of original dtype
expected = pd.Series([9 * off, 8 * off], name='xxx', dtype=object)
tm.assert_series_equal(per - ser, expected)
tm.assert_series_equal(ser - per, -1 * expected)

s2 = pd.Series([pd.Period('2015-01-05', freq='D'),
pd.Period('2015-01-04', freq='D')], name='xxx')
assert s2.dtype == object

expected = pd.Series([4 * off, 2 * off], name='xxx', dtype=object)
tm.assert_series_equal(s2 - ser, expected)
tm.assert_series_equal(ser - s2, -1 * expected)


class TestTimestampSeriesArithmetic(object):
def test_timestamp_sub_series(self):
ser = pd.Series(pd.date_range('2014-03-17', periods=2, freq='D',
tz='US/Eastern'))
ts = ser[0]

delta_series = pd.Series([np.timedelta64(0, 'D'),
np.timedelta64(1, 'D')])
tm.assert_series_equal(ser - ts, delta_series)
tm.assert_series_equal(ts - ser, -delta_series)

def test_dt64ser_sub_datetime_dtype(self):
ts = Timestamp(datetime(1993, 1, 7, 13, 30, 00))
dt = datetime(1993, 6, 22, 13, 30)
ser = Series([ts])
result = pd.to_timedelta(np.abs(ser - dt))
assert result.dtype == 'timedelta64[ns]'