Skip to content
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

Add dayofyear and dayofweek accessors to CFTimeIndex #2599

Merged
merged 1 commit into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
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
6 changes: 4 additions & 2 deletions doc/time-series.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,16 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports:
da.sel(time=slice('0001-05', '0002-02'))
- Access of basic datetime components via the ``dt`` accessor (in this case
just "year", "month", "day", "hour", "minute", "second", "microsecond", and
"season"):
just "year", "month", "day", "hour", "minute", "second", "microsecond",
"season", "dayofyear", and "dayofweek"):

.. ipython:: python
da.time.dt.year
da.time.dt.month
da.time.dt.season
da.time.dt.dayofyear
da.time.dt.dayofweek
- Group-by operations based on datetime accessor attributes (e.g. by month of
the year):
Expand Down
3 changes: 3 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ Enhancements
- :py:class:`CFTimeIndex` uses slicing for string indexing when possible (like
:py:class:`pandas.DatetimeIndex`), which avoids unnecessary copies.
By `Stephan Hoyer <https://github.com/shoyer>`_
- Like :py:class:`pandas.DatetimeIndex`, :py:class:`CFTimeIndex` now supports
"dayofyear" and "dayofweek" accessors (:issue:`2597`). By `Spencer Clark
<https://github.com/spencerkclark>`_.

Bug fixes
~~~~~~~~~
Expand Down
3 changes: 3 additions & 0 deletions xarray/coding/cftimeindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ class CFTimeIndex(pd.Index):
second = _field_accessor('second', 'The seconds of the datetime')
microsecond = _field_accessor('microsecond',
'The microseconds of the datetime')
dayofyear = _field_accessor('dayofyr',
'The ordinal day of year of the datetime')
dayofweek = _field_accessor('dayofwk', 'The day of week of the datetime')
date_type = property(get_date_type)

def __new__(cls, data, name=None):
Expand Down
9 changes: 6 additions & 3 deletions xarray/tests/test_accessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ def times_3d(times):


@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
@pytest.mark.parametrize('field', ['year', 'month', 'day', 'hour'])
@pytest.mark.parametrize('field', ['year', 'month', 'day', 'hour',
'dayofyear', 'dayofweek'])
def test_field_access(data, field):
result = getattr(data.time.dt, field)
expected = xr.DataArray(
Expand All @@ -170,7 +171,8 @@ def test_field_access(data, field):

@pytest.mark.skipif(not has_dask, reason='dask not installed')
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
@pytest.mark.parametrize('field', ['year', 'month', 'day', 'hour'])
@pytest.mark.parametrize('field', ['year', 'month', 'day', 'hour',
'dayofyear', 'dayofweek'])
def test_dask_field_access_1d(data, field):
import dask.array as da

Expand All @@ -186,7 +188,8 @@ def test_dask_field_access_1d(data, field):

@pytest.mark.skipif(not has_dask, reason='dask not installed')
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
@pytest.mark.parametrize('field', ['year', 'month', 'day', 'hour'])
@pytest.mark.parametrize('field', ['year', 'month', 'day', 'hour', 'dayofyear',
'dayofweek'])
def test_dask_field_access(times_3d, data, field):
import dask.array as da

Expand Down
14 changes: 14 additions & 0 deletions xarray/tests/test_cftimeindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,20 @@ def test_cftimeindex_field_accessors(index, field, expected):
assert_array_equal(result, expected)


@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
def test_cftimeindex_dayofyear_accessor(index):
result = index.dayofyear
expected = [date.dayofyr for date in index]
assert_array_equal(result, expected)


@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
def test_cftimeindex_dayofweek_accessor(index):
result = index.dayofweek
expected = [date.dayofwk for date in index]
assert_array_equal(result, expected)


@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
@pytest.mark.parametrize(('string', 'date_args', 'reso'), [
('1999', (1999, 1, 1), 'year'),
Expand Down