Skip to content

Switch the name of datetime components from 'time.month' to 'month' #351

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 1 commit into from
Mar 2, 2015
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
8 changes: 8 additions & 0 deletions doc/data-structures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ __ http://pandas.pydata.org/pandas-docs/stable/api.html#time-date-components
foo['time.month']
foo['time.dayofyear']

xray adds ``'season'`` to the list of datetime components supported by pandas:

.. ipython:: python

foo['time.season']

The set of valid seasons consists of 'DJF', 'MAM', 'JJA' and 'SON', labeled by
the first letters of the corresponding months.

Dataset
-------
Expand Down
35 changes: 24 additions & 11 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ Breaking changes
rhs = xray.DataArray([2, 3, 4], [('x', [1, 2, 3])])
lhs + rhs

For :ref:`data construction and merging<merge>`, we align based on the
:ref:`For dataset construction and merging<merge>`, we align based on the
**union** of labels:

.. ipython:: python

xray.Dataset({'foo': lhs, 'bar': rhs})

For :ref:`update and __setitem__<update>`, we align based on the **original**
:ref:`For update and __setitem__<update>`, we align based on the **original**
object:

.. ipython:: python
Expand Down Expand Up @@ -76,15 +76,19 @@ Breaking changes

This functionality can be controlled through the ``compat`` option, which
has also been added to the :py:class:`~xray.Dataset` constructor.
- We have updated our use of the terms of "coordinates" and "variables". What
were known in previous versions of xray as "coordinates" and "variables" are
now referred to throughout the documentation as "coordinate variables" and
"data variables". This brings xray in closer alignment to `CF Conventions`_.
The only visible change besides the documentation is that ``Dataset.vars``
has been renamed ``Dataset.data_vars``.
- You will need to update your code if you have been ignoring deprecation
warnings: methods and attributes that were deprecated in xray v0.3 or earlier
(e.g., ``dimensions``, ``attributes```) have gone away.
- Datetime shortcuts such as ``'time.month'`` now return a ``DataArray`` with
the name ``'month'``, not ``'time.month'`` (:issue:`345`). This makes it
easier to index the resulting arrays when they are used with ``groupby``:

.. ipython:: python

time = xray.DataArray(pd.date_range('2000-01-01', periods=365),
dims='time', name='time')
counts = time.groupby('time.month').count()
counts.sel(month=2)

Previously, you would need to use something like
``counts.sel(**{'time.month': 2}})``, which is much more awkward.
- The ``season`` datetime shortcut now returns an array of string labels
such `'DJF'`:

Expand All @@ -94,6 +98,15 @@ Breaking changes
ds['t.season']

Previously, it returned numbered seasons 1 through 4.
- We have updated our use of the terms of "coordinates" and "variables". What
were known in previous versions of xray as "coordinates" and "variables" are
now referred to throughout the documentation as "coordinate variables" and
"data variables". This brings xray in closer alignment to `CF Conventions`_.
The only visible change besides the documentation is that ``Dataset.vars``
has been renamed ``Dataset.data_vars``.
- You will need to update your code if you have been ignoring deprecation
warnings: methods and attributes that were deprecated in xray v0.3 or earlier
(e.g., ``dimensions``, ``attributes```) have gone away.

.. _bottleneck: https://github.com/kwgoodman/bottleneck

Expand Down
6 changes: 6 additions & 0 deletions xray/core/dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ def _new_from_dataset(cls, dataset, name):
"""
obj = object.__new__(cls)
obj._dataset = dataset._copy_listed([name], keep_attrs=False)
if name not in obj._dataset:
# handle virtual variables
try:
_, name = name.split('.', 1)
except Exception:
raise KeyError(name)
obj._name = name
if name not in dataset._dims:
obj._dataset._coord_names.discard(name)
Expand Down
21 changes: 11 additions & 10 deletions xray/core/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,27 +137,27 @@ def _get_virtual_variable(variables, key):
if not isinstance(key, basestring):
raise KeyError(key)

split_key = key.split('.')
split_key = key.split('.', 1)
if len(split_key) != 2:
raise KeyError(key)

ref_var_name, suffix = split_key
ref_var = variables[ref_var_name]
ref_name, var_name = split_key
ref_var = variables[ref_name]
if ref_var.ndim == 1:
date = ref_var.to_index()
elif ref_var.ndim == 0:
date = pd.Timestamp(ref_var.values)
else:
raise KeyError(key)

if suffix == 'season':
if var_name == 'season':
# TODO: move 'season' into pandas itself
seasons = np.array(['DJF', 'MAM', 'JJA', 'SON'])
month = date.month
data = seasons[(month // 3) % 4]
else:
data = getattr(date, suffix)
return ref_var_name, variable.Variable(ref_var.dims, data)
data = getattr(date, var_name)
return ref_name, var_name, variable.Variable(ref_var.dims, data)


def _as_dataset_variable(name, var):
Expand Down Expand Up @@ -624,10 +624,11 @@ def _copy_listed(self, names, keep_attrs=True):
try:
variables[name] = self._variables[name]
except KeyError:
ref_name, var = _get_virtual_variable(self._variables, name)
variables[name] = var
ref_name, var_name, var = _get_virtual_variable(
self._variables, name)
variables[var_name] = var
if ref_name in self._coord_names:
coord_names.add(name)
coord_names.add(var_name)

needed_dims = set()
for v in variables.values():
Expand All @@ -647,7 +648,7 @@ def __copy__(self):
return self.copy(deep=False)

def __deepcopy__(self, memo=None):
# memo does nothing but is required for compatability with
# memo does nothing but is required for compatibility with
# copy.deepcopy
return self.copy(deep=True)

Expand Down
9 changes: 5 additions & 4 deletions xray/test/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -965,8 +965,9 @@ def test_getitem(self):
def test_virtual_variables(self):
# access virtual variables
data = create_test_data()
self.assertVariableEqual(data['time.dayofyear'],
Variable('time', 1 + np.arange(20)))
expected = DataArray(1 + np.arange(20), coords=[data['time']],
dims='time', name='dayofyear')
self.assertDataArrayIdentical(expected, data['time.dayofyear'])
self.assertArrayEqual(data['time.month'].values,
data.variables['time'].to_index().month)
self.assertArrayEqual(data['time.season'].values, 'DJF')
Expand All @@ -975,7 +976,7 @@ def test_virtual_variables(self):
self.assertArrayEqual(np.sin(data['time.dayofyear']),
np.sin(1 + np.arange(20)))
# ensure they become coordinates
expected = Dataset({}, {'time.dayofyear': data['time.dayofyear']})
expected = Dataset({}, {'dayofyear': data['time.dayofyear']})
actual = data[['time.dayofyear']]
self.assertDatasetEqual(expected, actual)
# non-coordinate variables
Expand Down Expand Up @@ -1190,7 +1191,7 @@ def test_groupby_math_virtual(self):
grouped = ds.groupby('t.day')
actual = grouped - grouped.mean()
expected = Dataset({'x': ('t', [0, 0, 0])},
{'t': ds['t'], 't.day': ds['t.day']})
ds[['t', 't.day']])
self.assertDatasetIdentical(actual, expected)

def test_groupby_nan(self):
Expand Down