-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Options to binary ops kwargs #1065
Changes from 3 commits
3b04fb0
643fa49
43df4d0
ebb2ad0
ab717fa
8aa969b
46ad36a
4a05ca4
a7b7497
88c37bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
assert_unique_multiindex_level_names) | ||
from .formatting import format_item | ||
from .utils import decode_numpy_dict_values, ensure_us_time_resolution | ||
from .options import OPTIONS | ||
|
||
|
||
def _infer_coords_and_dims(shape, coords, dims): | ||
|
@@ -1377,13 +1378,15 @@ def func(self, *args, **kwargs): | |
return func | ||
|
||
@staticmethod | ||
def _binary_op(f, reflexive=False, join='inner', **ignored_kwargs): | ||
def _binary_op(f, reflexive=False, join=None, **ignored_kwargs): | ||
@functools.wraps(f) | ||
def func(self, other): | ||
if isinstance(other, (Dataset, groupby.GroupBy)): | ||
return NotImplemented | ||
if hasattr(other, 'indexes'): | ||
self, other = align(self, other, join=join, copy=False) | ||
# if user does not specify join, default to OPTIONS['join'] | ||
how_to_join = join or OPTIONS['join'] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would trigger an UnboundLocalError: So the choice is either I opted for (2) for simplicity. Is the style of (1) generally preferred here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could do the But yes, I do prefer explicitly checking against There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Funny, your suggestion is the same as my first edit to the code, but then my teammates suggested I should use the other options. Nomenclature is not my forte. I'll make the default
if there's no objection. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also align in other operations, e.g., There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. alright, I'm using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I think |
||
self, other = align(self, other, join=how_to_join, copy=False) | ||
other_variable = getattr(other, 'variable', other) | ||
other_coords = getattr(other, 'coords', None) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
OPTIONS = {'display_width': 80} | ||
OPTIONS = {'display_width': 80, | ||
'join': "inner"} | ||
|
||
|
||
class set_options(object): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you update the docstring for this class? |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2268,3 +2268,35 @@ def test_dot(self): | |
da.dot(dm.values) | ||
with self.assertRaisesRegexp(ValueError, 'no shared dimensions'): | ||
da.dot(DataArray(1)) | ||
|
||
def test_binary_op_join_setting(self): | ||
""" | ||
A test method to verify the ability to set binary operation join kwarg | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Usually we don't put docstrings on test methods There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool. Will remove. |
||
("inner", "outer", "left", "right") via xr.set_options(). | ||
""" | ||
# First we set up a data array | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These sort of comments (repeating the code) just add noise |
||
xdim, ydim, zdim = 'x', 'y', 'z' | ||
xcoords, ycoords, zcoords = ['a', 'b', 'c'], [-2, 0, 2], [0, 1, 2] | ||
total_size = len(xcoords) * len(ycoords) * len(zcoords) | ||
# create a 3-by-3-by-3 data array | ||
arr = xr.DataArray(np.arange(total_size).\ | ||
reshape(len(xcoords),len(ycoords),len(zcoords)), | ||
[(xdim, xcoords), (ydim, ycoords),(zdim, zcoords)]) | ||
# now create a data array with the last x slice missing | ||
missing_last_x = arr[0:-1,:,:].copy() | ||
# create another data array with the last z slice missing | ||
missing_last_z = arr[:,:,0:-1].copy() | ||
# because the default in OPTIONS is join="inner", we test "outer" first | ||
xr.set_options(join="outer") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the context manager for tests instead (e.g, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will do |
||
result = missing_last_x + missing_last_z | ||
self.assertTrue(result.shape == arr.shape) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of checking specific properties, construct the full expected result (e.g., by calling |
||
self.assertTrue(result[-1,:,:].isnull().all()) | ||
self.assertTrue(result[:,:,-1].isnull().all()) | ||
# now revert back to join="inner" | ||
xr.set_options(join="inner") | ||
result = missing_last_x + missing_last_z | ||
self.assertTrue(result.shape == \ | ||
(len(xcoords)-1, len(ycoords), len(zcoords)-1)) | ||
self.assertTrue(result.notnull().all()) | ||
self.assertFalse('c' in list(result['x'])) | ||
self.assertFalse(2 in list(result['z'])) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
|
||
import numpy as np | ||
import pandas as pd | ||
import xarray as xr | ||
import pytest | ||
|
||
from xarray import (align, broadcast, concat, merge, conventions, backends, | ||
|
@@ -2916,6 +2917,44 @@ def test_filter_by_attrs(self): | |
for var in new_ds.data_vars: | ||
self.assertEqual(new_ds[var].height, '10 m') | ||
|
||
def test_binary_op_join_setting(self): | ||
""" | ||
A test method to verify the ability to set binary operation join kwarg | ||
("inner", "outer", "left", "right") via xr.set_options(). | ||
""" | ||
# First we set up a data array | ||
xdim, ydim, zdim = 'x', 'y', 'z' | ||
xcoords, ycoords, zcoords = ['a', 'b', 'c'], [-2, 0, 2], [0, 1, 2] | ||
total_size = len(xcoords) * len(ycoords) * len(zcoords) | ||
# create a 3-by-3-by-3 data array | ||
arr = DataArray(np.arange(total_size).\ | ||
reshape(len(xcoords),len(ycoords),len(zcoords)), | ||
[(xdim, xcoords), (ydim, ycoords),(zdim, zcoords)]) | ||
# now create a data array with the last x slice missing | ||
arr1 = arr[0:-1,:,:].copy() | ||
missing_last_x = arr1.to_dataset(name='foo') | ||
# create another data array with the last z slice missing | ||
arr2 = arr[:,:,0:-1].copy() | ||
missing_last_z = arr2.to_dataset(name='foo') # needs to be name='foo' as well | ||
# because the default in OPTIONS is join="inner", we test "outer" first | ||
xr.set_options(join="outer") | ||
result = missing_last_x + missing_last_z | ||
self.assertTrue(result.foo.shape == arr.shape) | ||
self.assertTrue(result.foo[-1,:,:].isnull().all()) | ||
self.assertTrue(result.foo[:,:,-1].isnull().all()) | ||
# now revert back to join="inner" | ||
xr.set_options(join="inner") | ||
result = missing_last_x + missing_last_z | ||
self.assertTrue(result.foo.shape == \ | ||
(len(xcoords)-1, len(ycoords), len(zcoords)-1)) | ||
self.assertTrue(result.foo.notnull().all()) | ||
self.assertFalse('c' in list(result.foo['x'])) | ||
self.assertFalse(2 in list(result.foo['z'])) | ||
# just for kicks, what happens when the dataarrays have different names? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have tests for similar behavior -- see It does raise the interesting question of what the behavior should be when |
||
misnomer = arr1.to_dataset(name='bar') | ||
result = missing_last_x + misnomer | ||
self.assertTrue(len(result.data_vars)==0) # empty dataset | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. too much white space here -- by convention, leave only 2 blank lines |
||
|
||
### Py.test tests | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment just states what the code does, so it would be better to leave it out