Skip to content

REF/TST: Add more pytest idiom to tests/resample #24230

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 12 commits into from
Dec 13, 2018
Merged
Show file tree
Hide file tree
Changes from 4 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
35 changes: 33 additions & 2 deletions pandas/tests/resample/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import numpy as np
import pytest

from pandas.tests.resample.test_base import (
downsample_methods, resample_methods, upsample_methods)
from pandas import Series
from pandas.core.indexes.datetimes import date_range
from pandas.core.indexes.period import period_range

# The various methods we support
downsample_methods = ['min', 'max', 'first', 'last', 'sum', 'mean', 'sem',
'median', 'prod', 'var', 'std', 'ohlc', 'quantile']
upsample_methods = ['count', 'size']
series_methods = ['nunique']
resample_methods = downsample_methods + upsample_methods + series_methods


@pytest.fixture(params=downsample_methods)
Expand All @@ -20,3 +29,25 @@ def upsample_method(request):
def resample_method(request):
"""Fixture for parametrization of Grouper resample methods."""
return request.param


@pytest.fixture()
def simple_date_range_series():
"""
Series with date range index and random data for test purposes.
"""
def _simple_date_range_series(start, end, freq='D'):
rng = date_range(start, end, freq=freq)
return Series(np.random.randn(len(rng)), index=rng)
return _simple_date_range_series


@pytest.fixture()
def simple_period_range_series():
"""
Series with period range index and random data for test purposes.
"""
def _simple_period_range_series(start, end, freq='D'):
rng = period_range(start, end, freq=freq)
return Series(np.random.randn(len(rng)), index=rng)
return _simple_period_range_series
107 changes: 37 additions & 70 deletions pandas/tests/resample/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,14 @@
import pandas as pd
from pandas import DataFrame, Series
from pandas.core.groupby.groupby import DataError
from pandas.core.indexes.datetimes import date_range
from pandas.core.indexes.period import PeriodIndex, period_range
from pandas.core.indexes.period import PeriodIndex
from pandas.core.indexes.timedeltas import TimedeltaIndex
from pandas.core.resample import TimeGrouper
import pandas.util.testing as tm
from pandas.util.testing import (
assert_almost_equal, assert_frame_equal, assert_index_equal,
assert_series_equal)

from pandas.tseries.offsets import BDay

business_day_offset = BDay()

# The various methods we support
downsample_methods = ['min', 'max', 'first', 'last', 'sum', 'mean', 'sem',
'median', 'prod', 'var', 'std', 'ohlc', 'quantile']
upsample_methods = ['count', 'size']
series_methods = ['nunique']
resample_methods = downsample_methods + upsample_methods + series_methods


def simple_date_range_series(start, end, freq='D'):
"""
Series with date range index and random data for test purposes.
"""
rng = date_range(start, end, freq=freq)
return Series(np.random.randn(len(rng)), index=rng)


def simple_period_range_series(start, end, freq='D'):
"""
Series with period range index and random data for test purposes.
"""
rng = period_range(start, end, freq=freq)
return Series(np.random.randn(len(rng)), index=rng)


class Base(object):
"""
Expand Down Expand Up @@ -137,64 +109,59 @@ def test_raises_on_non_datetimelike_index(self):
xp = DataFrame()
pytest.raises(TypeError, lambda: xp.resample('A').mean())

def test_resample_empty_series(self):
@pytest.mark.parametrize('freq', ['M', 'D', 'H'])
def test_resample_empty_series(self, freq, resample_method):
# GH12771 & GH12868

if resample_method == 'ohlc':
pytest.skip('need to test for ohlc from GH13083')

s = self.create_series()[:0]
result = getattr(s.resample(freq), resample_method)()

for freq in ['M', 'D', 'H']:
# need to test for ohlc from GH13083
methods = [method for method in resample_methods
if method != 'ohlc']
for method in methods:
result = getattr(s.resample(freq), method)()

expected = s.copy()
expected.index = s.index._shallow_copy(freq=freq)
assert_index_equal(result.index, expected.index)
assert result.index.freq == expected.index.freq
assert_series_equal(result, expected, check_dtype=False)

def test_resample_empty_dataframe(self):
expected = s.copy()
expected.index = s.index._shallow_copy(freq=freq)
assert_index_equal(result.index, expected.index)
assert result.index.freq == expected.index.freq
assert_series_equal(result, expected, check_dtype=False)

@pytest.mark.parametrize('freq', ['M', 'D', 'H'])
def test_resample_empty_dataframe(self, freq, resample_method):
# GH13212
index = self.create_series().index[:0]
f = DataFrame(index=index)

for freq in ['M', 'D', 'H']:
# count retains dimensions too
methods = downsample_methods + upsample_methods
for method in methods:
result = getattr(f.resample(freq), method)()
if method != 'size':
expected = f.copy()
else:
# GH14962
expected = Series([])

expected.index = f.index._shallow_copy(freq=freq)
assert_index_equal(result.index, expected.index)
assert result.index.freq == expected.index.freq
assert_almost_equal(result, expected, check_dtype=False)

# test size for GH13212 (currently stays as df)
# count retains dimensions too
result = getattr(f.resample(freq), resample_method)()
if resample_method != 'size':
expected = f.copy()
else:
# GH14962
expected = Series([])

expected.index = f.index._shallow_copy(freq=freq)
assert_index_equal(result.index, expected.index)
assert result.index.freq == expected.index.freq
assert_almost_equal(result, expected, check_dtype=False)

# test size for GH13212 (currently stays as df)

@pytest.mark.parametrize("index", tm.all_timeseries_index_generator(0))
@pytest.mark.parametrize(
"dtype",
[np.float, np.int, np.object, 'datetime64[ns]'])
def test_resample_empty_dtypes(self, index, dtype):
def test_resample_empty_dtypes(self, index, dtype, resample_method):

# Empty series were sometimes causing a segfault (for the functions
# with Cython bounds-checking disabled) or an IndexError. We just run
# them to ensure they no longer do. (GH #10228)
for how in downsample_methods + upsample_methods:
empty_series = Series([], index, dtype)
try:
getattr(empty_series.resample('d'), how)()
except DataError:
# Ignore these since some combinations are invalid
# (ex: doing mean with dtype of np.object)
pass
empty_series = Series([], index, dtype)
try:
getattr(empty_series.resample('d'), resample_method)()
except DataError:
# Ignore these since some combinations are invalid
# (ex: doing mean with dtype of np.object)
pass

def test_resample_loffset_arg_type(self):
# GH 13218, 15002
Expand Down
63 changes: 31 additions & 32 deletions pandas/tests/resample/test_datetime_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@
from pandas.core.indexes.period import Period, period_range
from pandas.core.indexes.timedeltas import timedelta_range
from pandas.core.resample import DatetimeIndex, TimeGrouper
from pandas.tests.resample.test_base import (
Base, business_day_offset, downsample_methods, simple_date_range_series,
simple_period_range_series)
from pandas.tests.resample.test_base import Base
import pandas.util.testing as tm
from pandas.util.testing import (
assert_almost_equal, assert_frame_equal, assert_series_equal)

import pandas.tseries.offsets as offsets
from pandas.tseries.offsets import Minute
from pandas.tseries.offsets import BDay, Minute


class TestDatetimeIndex(Base):
Expand Down Expand Up @@ -131,7 +129,7 @@ def test_resample_string_kwargs(self):
with pytest.raises(ValueError):
s.resample('5min', convention='starttt').mean()

def test_resample_how(self):
def test_resample_how(self, downsample_method):
rng = date_range('1/1/2000 00:00:00', '1/1/2000 00:13:00', freq='min',
name='index')
s = Series(np.random.randn(14), index=rng)
Expand All @@ -140,7 +138,7 @@ def test_resample_how(self):
grouplist[1:6] = 1
grouplist[6:11] = 2
grouplist[11:] = 3
args = downsample_methods
arg = downsample_method
Copy link
Contributor

Choose a reason for hiding this comment

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

it might be worthile to move ohlc to a separate test


def _ohlc(group):
if isna(group).all():
Expand All @@ -149,29 +147,28 @@ def _ohlc(group):

inds = date_range('1/1/2000', periods=4, freq='5min', name='index')

for arg in args:
if arg == 'ohlc':
func = _ohlc
else:
func = arg
try:
result = getattr(s.resample(
'5min', closed='right', label='right'), arg)()

expected = s.groupby(grouplist).agg(func)
assert result.index.name == 'index'
if arg == 'ohlc':
func = _ohlc
expected = DataFrame(expected.values.tolist())
expected.columns = ['open', 'high', 'low', 'close']
expected.index = Index(inds, name='index')
assert_frame_equal(result, expected)
else:
func = arg
try:
result = getattr(s.resample(
'5min', closed='right', label='right'), arg)()

expected = s.groupby(grouplist).agg(func)
assert result.index.name == 'index'
if arg == 'ohlc':
expected = DataFrame(expected.values.tolist())
expected.columns = ['open', 'high', 'low', 'close']
expected.index = Index(inds, name='index')
assert_frame_equal(result, expected)
else:
expected.index = inds
assert_series_equal(result, expected)
except BaseException as exc:

exc.args += ('how=%s' % arg,)
raise
expected.index = inds
assert_series_equal(result, expected)
except BaseException as exc:
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 remove this catching of BaseException (e.g. the try/accept), with parameterized methods it is uncessary


exc.args += ('how=%s' % arg,)
raise

def test_numpy_compat(self):
# see gh-12811
Expand Down Expand Up @@ -432,6 +429,7 @@ def test_resample_loffset(self, loffset):

# to weekly
result = ser.resample('w-sun').last()
business_day_offset = BDay()
expected = ser.resample('w-sun', loffset=-business_day_offset).last()
assert result.index[0] - business_day_offset == expected.index[0]

Expand Down Expand Up @@ -628,7 +626,7 @@ def test_resample_reresample(self):
assert isinstance(result.index.freq, offsets.DateOffset)
assert result.index.freq == offsets.Hour(8)

def test_resample_timestamp_to_period(self):
def test_resample_timestamp_to_period(self, simple_date_range_series):
ts = simple_date_range_series('1/1/1990', '1/1/2000')

result = ts.resample('A-DEC', kind='period').mean()
Expand Down Expand Up @@ -945,7 +943,7 @@ def test_nanosecond_resample_error(self):

assert_series_equal(result, exp)

def test_resample_anchored_intraday(self):
def test_resample_anchored_intraday(self, simple_date_range_series):
# #1471, #1458

rng = date_range('1/1/2012', '4/1/2012', freq='100min')
Expand Down Expand Up @@ -985,7 +983,7 @@ def test_resample_anchored_intraday(self):
resampled = ts.resample('M').mean()
assert len(resampled) == 1

def test_resample_anchored_monthstart(self):
def test_resample_anchored_monthstart(self, simple_date_range_series):
ts = simple_date_range_series('1/1/2000', '12/31/2002')

freqs = ['MS', 'BMS', 'QS-MAR', 'AS-DEC', 'AS-JUN']
Expand Down Expand Up @@ -1015,7 +1013,8 @@ def test_resample_anchored_multiday(self):
result = s.resample('2200L', label='right').mean()
assert result.index[-1] == Timestamp('2014-10-15 23:00:04.200')

def test_corner_cases(self):
def test_corner_cases(self, simple_period_range_series,
simple_date_range_series):
# miscellaneous test coverage

rng = date_range('1/1/2000', periods=12, freq='t')
Expand Down Expand Up @@ -1078,7 +1077,7 @@ def test_resample_median_bug_1688(self):
exp = df.asfreq('T')
tm.assert_frame_equal(result, exp)

def test_how_lambda_functions(self):
def test_how_lambda_functions(self, simple_date_range_series):

ts = simple_date_range_series('1/1/2000', '4/1/2000')

Expand Down
Loading