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
ENH: finite difference method diff
#495
Conversation
Actually, the current implementation leads to Do you agree, or do you prefer this |
This looks very nice -- thanks for putting together the PR!
I wouldn't bother with this. It's not so elegant, and
I wouldn't allow full control here, but maybe a keyword argument for choosing whether to take the "lower", "upper" or "mean" labels would be appropriate.
I agree. It would be better to skip those variables entirely, like the current behavior for aggregation functions like mean. |
return self | ||
if n < 0: | ||
raise ValueError('order `n` must be non-negative but got {}' | ||
''.format((n))) |
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.
nit: one extra pair of parenthesis around n
I don't see how 'mean' could work, as the coord might be of dtype str. |
I'm not really happy with my implementation; the coordinate/variable handling in lines 1870-1884 are far from elegant. But is there a nicer way to do this? |
if dim in var.dims or not var.dims: | ||
if name not in self.coords: | ||
variables[name] = end[name] - start[name] | ||
variables[dim] = variables[name].coords[dim] |
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.
I would try:
kwargs_new = kwargs_end if coord_new == 'upper' else kwargs_start
for name, var in iteritems(self.variables):
if dim in var.dims:
if name in self.data_vars:
variables[name] = var.isel(**kwargs_end) - var.isel(**kwargs_start)
else:
# don't do arithmetic on coordinates
variables[name] = var.isel(**kwargs_new)
else:
# these variables should be unchanged
variables[name] = var
# this private constructor preserves existing coordinates
# it's also much faster, because it doesn't need to do validation
difference = self._replace_vars_and_dims(variables)
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 private constructor preserves existing coordinates
it's also much faster, because it doesn't need to do validation
difference = self._replace_vars_and_dims(variables)
_replace_vars_and_dims gave me an error because the size of the
dimension on which I do the diff is changing. Was I using it wrongly?
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.
Let me test your PR and debug this. My guess is that some of the variables were ending up with inconsistent dimension sizes (the Dataset constructor resolves that by doing an outer join of the index labels).
Indeed, this would fail for string dtypes. I can see some possible utility in centered coordinates, especially for second order differences. We can certainly leave this for later, though. |
Just made a PR against your branch with my suggestion: https://github.com/andreas-h/xray/pull/1 It looks like it's working now. |
This could also use a bit of documentation -- at least mention on "What's New" and in the API docs. |
if n == 0: | ||
return self | ||
if n < 0: | ||
raise ValueError('order `n` must be non-negative but got {}' |
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.
please add a test that catches each of these exceptions
@andreas-h we're going to release v0.6 in the next day or two. I'd love to include this enhancement in it if you have the time to finish it up :). |
That's strange, I cannot reproduce the test failure on my system ... Any ideas? |
Could you try doing |
# prepare new coordinate | ||
if label == 'upper': | ||
kwargs_new = kwargs_end | ||
elif label == 'lower': |
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.
looks like we still need a unit test for label='lower'
ENH: finite difference method `diff`
OK, merging. Thank you! |
adds
diff
method to bothDataArray
andDataset
. closes #490Still to be done:
Possible enhancements:
axis
instead ofdim
forDataArray
objects. The signature would then beDataArray.diff(dim=None, n=1, axis=None)
and I would need to check that exactly one ofdim
andaxis
isNone
. I find it a bit ugly;DataArray.diff(n=1, dim=None, axis=None)
would be nicer in my view. But then the signatures forDataArray.diff
andDataset.diff
would be different, which is also not nice.coord
kwarg instead of just taking the coordinate values of the upper bounds.What do you think?