-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Accept int value in head, thin and tail #3298
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
Changes from all commits
ad7560e
5d76cd6
6ca0b42
d9cbcda
4fec603
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 |
---|---|---|
|
@@ -2009,15 +2009,18 @@ def sel( | |
return result._overwrite_indexes(new_indexes) | ||
|
||
def head( | ||
self, indexers: Mapping[Hashable, Any] = None, **indexers_kwargs: Any | ||
self, | ||
indexers: Union[Mapping[Hashable, int], int] = None, | ||
**indexers_kwargs: Any | ||
) -> "Dataset": | ||
"""Returns a new dataset with the first `n` values of each array | ||
for the specified dimension(s). | ||
|
||
Parameters | ||
---------- | ||
indexers : dict, optional | ||
A dict with keys matching dimensions and integer values `n`. | ||
indexers : dict or int, default: 5 | ||
A dict with keys matching dimensions and integer values `n` | ||
or a single integer `n` applied over all dimensions. | ||
One of indexers or indexers_kwargs must be provided. | ||
**indexers_kwargs : {dim: n, ...}, optional | ||
The keyword arguments form of ``indexers``. | ||
|
@@ -2030,20 +2033,41 @@ def head( | |
Dataset.thin | ||
DataArray.head | ||
""" | ||
if not indexers_kwargs: | ||
if indexers is None: | ||
indexers = 5 | ||
if not isinstance(indexers, int) and not is_dict_like(indexers): | ||
raise TypeError("indexers must be either dict-like or a single integer") | ||
if isinstance(indexers, int): | ||
indexers = {dim: indexers for dim in self.dims} | ||
indexers = either_dict_or_kwargs(indexers, indexers_kwargs, "head") | ||
indexers = {k: slice(val) for k, val in indexers.items()} | ||
return self.isel(indexers) | ||
for k, v in indexers.items(): | ||
if not isinstance(v, int): | ||
raise TypeError( | ||
"expected integer type indexer for " | ||
"dimension %r, found %r" % (k, type(v)) | ||
) | ||
elif v < 0: | ||
raise ValueError( | ||
"expected positive integer as indexer " | ||
"for dimension %r, found %s" % (k, v) | ||
) | ||
indexers_slices = {k: slice(val) for k, val in indexers.items()} | ||
return self.isel(indexers_slices) | ||
|
||
def tail( | ||
self, indexers: Mapping[Hashable, Any] = None, **indexers_kwargs: Any | ||
self, | ||
indexers: Union[Mapping[Hashable, int], int] = None, | ||
**indexers_kwargs: Any | ||
) -> "Dataset": | ||
"""Returns a new dataset with the last `n` values of each array | ||
for the specified dimension(s). | ||
|
||
Parameters | ||
---------- | ||
indexers : dict, optional | ||
A dict with keys matching dimensions and integer values `n`. | ||
indexers : dict or int, default: 5 | ||
A dict with keys matching dimensions and integer values `n` | ||
or a single integer `n` applied over all dimensions. | ||
One of indexers or indexers_kwargs must be provided. | ||
**indexers_kwargs : {dim: n, ...}, optional | ||
The keyword arguments form of ``indexers``. | ||
|
@@ -2056,24 +2080,44 @@ def tail( | |
Dataset.thin | ||
DataArray.tail | ||
""" | ||
|
||
if not indexers_kwargs: | ||
if indexers is None: | ||
indexers = 5 | ||
if not isinstance(indexers, int) and not is_dict_like(indexers): | ||
raise TypeError("indexers must be either dict-like or a single integer") | ||
if isinstance(indexers, int): | ||
indexers = {dim: indexers for dim in self.dims} | ||
indexers = either_dict_or_kwargs(indexers, indexers_kwargs, "tail") | ||
indexers = { | ||
for k, v in indexers.items(): | ||
if not isinstance(v, int): | ||
raise TypeError( | ||
"expected integer type indexer for " | ||
"dimension %r, found %r" % (k, type(v)) | ||
) | ||
elif v < 0: | ||
raise ValueError( | ||
"expected positive integer as indexer " | ||
"for dimension %r, found %s" % (k, v) | ||
) | ||
indexers_slices = { | ||
k: slice(-val, None) if val != 0 else slice(val) | ||
for k, val in indexers.items() | ||
} | ||
return self.isel(indexers) | ||
return self.isel(indexers_slices) | ||
|
||
def thin( | ||
self, indexers: Mapping[Hashable, Any] = None, **indexers_kwargs: Any | ||
self, | ||
indexers: Union[Mapping[Hashable, int], int] = None, | ||
**indexers_kwargs: Any | ||
) -> "Dataset": | ||
"""Returns a new dataset with each array indexed along every `n`th | ||
value for the specified dimension(s) | ||
|
||
Parameters | ||
---------- | ||
indexers : dict, optional | ||
A dict with keys matching dimensions and integer values `n`. | ||
indexers : dict or int, default: 5 | ||
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. Does it make sense to thin by a factor of five by default? Or should we not have a default value? The use case for a default thinning value are less clear to me than defaults for head/tail. 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. Agree! 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. I think picking a default makes it very convenient to use. And this is a convenience method... 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. I set a default value to 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. I don't have a strong enough view. I agree it's a convenience method, but a convenient value significantly depends on the size of the array, unlike with So whatever you think. I'm probably a -0.2 |
||
A dict with keys matching dimensions and integer values `n` | ||
or a single integer `n` applied over all dimensions. | ||
One of indexers or indexers_kwargs must be provided. | ||
**indexers_kwargs : {dim: n, ...}, optional | ||
The keyword arguments form of ``indexers``. | ||
|
@@ -2086,11 +2130,30 @@ def thin( | |
Dataset.tail | ||
DataArray.thin | ||
""" | ||
if ( | ||
not indexers_kwargs | ||
and not isinstance(indexers, int) | ||
and not is_dict_like(indexers) | ||
): | ||
raise TypeError("indexers must be either dict-like or a single integer") | ||
if isinstance(indexers, int): | ||
indexers = {dim: indexers for dim in self.dims} | ||
indexers = either_dict_or_kwargs(indexers, indexers_kwargs, "thin") | ||
if 0 in indexers.values(): | ||
raise ValueError("step cannot be zero") | ||
indexers = {k: slice(None, None, val) for k, val in indexers.items()} | ||
return self.isel(indexers) | ||
for k, v in indexers.items(): | ||
if not isinstance(v, int): | ||
raise TypeError( | ||
"expected integer type indexer for " | ||
"dimension %r, found %r" % (k, type(v)) | ||
) | ||
elif v < 0: | ||
raise ValueError( | ||
"expected positive integer as indexer " | ||
"for dimension %r, found %s" % (k, v) | ||
) | ||
elif v == 0: | ||
raise ValueError("step cannot be zero") | ||
indexers_slices = {k: slice(None, None, val) for k, val in indexers.items()} | ||
return self.isel(indexers_slices) | ||
|
||
def broadcast_like( | ||
self, other: Union["Dataset", "DataArray"], exclude: Iterable[Hashable] = None | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1005,13 +1005,48 @@ def test_isel_drop(self): | |
def test_head(self): | ||
assert_equal(self.dv.isel(x=slice(5)), self.dv.head(x=5)) | ||
assert_equal(self.dv.isel(x=slice(0)), self.dv.head(x=0)) | ||
assert_equal( | ||
self.dv.isel({dim: slice(6) for dim in self.dv.dims}), self.dv.head(6) | ||
) | ||
assert_equal( | ||
self.dv.isel({dim: slice(5) for dim in self.dv.dims}), self.dv.head() | ||
) | ||
with raises_regex(TypeError, "either dict-like or a single int"): | ||
self.dv.head([3]) | ||
with raises_regex(TypeError, "expected integer type"): | ||
self.dv.head(x=3.1) | ||
with raises_regex(ValueError, "expected positive int"): | ||
self.dv.head(-3) | ||
|
||
def test_tail(self): | ||
assert_equal(self.dv.isel(x=slice(-5, None)), self.dv.tail(x=5)) | ||
assert_equal(self.dv.isel(x=slice(0)), self.dv.tail(x=0)) | ||
assert_equal( | ||
self.dv.isel({dim: slice(-6, None) for dim in self.dv.dims}), | ||
self.dv.tail(6), | ||
) | ||
assert_equal( | ||
self.dv.isel({dim: slice(-5, None) for dim in self.dv.dims}), self.dv.tail() | ||
) | ||
with raises_regex(TypeError, "either dict-like or a single int"): | ||
self.dv.tail([3]) | ||
with raises_regex(TypeError, "expected integer type"): | ||
self.dv.tail(x=3.1) | ||
with raises_regex(ValueError, "expected positive int"): | ||
self.dv.tail(-3) | ||
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. Very thorough tests! Thank you! |
||
|
||
def test_thin(self): | ||
assert_equal(self.dv.isel(x=slice(None, None, 5)), self.dv.thin(x=5)) | ||
assert_equal( | ||
self.dv.isel({dim: slice(None, None, 6) for dim in self.dv.dims}), | ||
self.dv.thin(6), | ||
) | ||
with raises_regex(TypeError, "either dict-like or a single int"): | ||
self.dv.thin([3]) | ||
with raises_regex(TypeError, "expected integer type"): | ||
self.dv.thin(x=3.1) | ||
with raises_regex(ValueError, "expected positive int"): | ||
self.dv.thin(-3) | ||
with raises_regex(ValueError, "cannot be zero"): | ||
self.dv.thin(time=0) | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.