issue_comments
8 rows where issue = 673757961 and user = 5635139 sorted by updated_at descending
This data as json, CSV (advanced)
Suggested facets: reactions, created_at (date), updated_at (date)
issue 1
- Recreate @gajomi's #2070 to keep attrs when calling astype() · 8 ✖
id | html_url | issue_url | node_id | user | created_at | updated_at ▲ | author_association | body | reactions | performed_via_github_app | issue |
---|---|---|---|---|---|---|---|---|---|---|---|
676539274 | https://github.com/pydata/xarray/pull/4314#issuecomment-676539274 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY3NjUzOTI3NA== | max-sixty 5635139 | 2020-08-19T16:47:02Z | 2020-08-19T16:47:02Z | MEMBER | I just saw I was up for reviewing this — sorry for missing that. Looks good. @keewis 's suggestion for the back-compat code looks like a nice refinement — it includes a version check which will ease disentangling it. Could we add that and then merge? |
{ "total_count": 1, "+1": 1, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 | |
673727756 | https://github.com/pydata/xarray/pull/4314#issuecomment-673727756 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY3MzcyNzc1Ng== | max-sixty 5635139 | 2020-08-13T21:50:15Z | 2020-08-13T21:50:15Z | MEMBER | There are some duplicated commits — 3x I'd suggest the squash and push -f...
|
{ "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 | |
673724685 | https://github.com/pydata/xarray/pull/4314#issuecomment-673724685 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY3MzcyNDY4NQ== | max-sixty 5635139 | 2020-08-13T21:41:40Z | 2020-08-13T21:41:40Z | MEMBER | The weirdest part is that the local diff is fine; here's the output of Sorry if I contributed to this. One override is to apply this patch on master and force push this branch. I'm happy to do it if @dnowacki-usgs agrees.
```diff
diff --git a/doc/whats-new.rst b/doc/whats-new.rst
index 793f72fb..4b7b117b 100644
--- a/doc/whats-new.rst
+++ b/doc/whats-new.rst
@@ -21,7 +21,9 @@ v0.16.1 (unreleased)
Breaking changes
~~~~~~~~~~~~~~~~
-
+- :py:meth:`DataArray.astype` and :py:meth:`Dataset.astype` now preserve attributes. Keep the
+ old behavior by passing `keep_attrs=False` (:issue:`2049`, :pull:`4314`).
+ By `Dan Nowacki <https://github.com/dnowacki-usgs>`_ and `Gabriel Joel Mitchell <https://github.com/gajomi>`_.
New Features
~~~~~~~~~~~~
diff --git a/xarray/core/common.py b/xarray/core/common.py
index bc5035b6..7b6fc13c 100644
--- a/xarray/core/common.py
+++ b/xarray/core/common.py
@@ -1305,6 +1305,48 @@ class DataWithCoords(SupportsArithmetic, AttrAccessMixin):
dask="allowed",
)
+ def astype(self, dtype, casting="unsafe", copy=True, keep_attrs=True):
+ """
+ Copy of the xarray object, with data cast to a specified type.
+ Leaves coordinate dtype unchanged.
+
+ Parameters
+ ----------
+ dtype : str or dtype
+ Typecode or data-type to which the array is cast.
+ casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
+ Controls what kind of data casting may occur. Defaults to 'unsafe'
+ for backwards compatibility.
+
+ * 'no' means the data types should not be cast at all.
+ * 'equiv' means only byte-order changes are allowed.
+ * 'safe' means only casts which can preserve values are allowed.
+ * 'same_kind' means only safe casts or casts within a kind,
+ like float64 to float32, are allowed.
+ * 'unsafe' means any data conversions may be done.
+ copy : bool, optional
+ By default, astype always returns a newly allocated array. If this
+ is set to False and the `dtype` requirement is satisfied, the input
+ array is returned instead of a copy.
+ keep_attrs : bool, optional
+ By default, astype keeps attributes. Set to False to remove
+ attributes in the returned object.
+
+ See also
+ --------
+ np.ndarray.astype
+ dask.array.Array.astype
+ """
+ from .computation import apply_ufunc
+
+ return apply_ufunc(
+ duck_array_ops.astype,
+ self,
+ kwargs=dict(dtype=dtype, casting=casting, copy=copy),
+ keep_attrs=keep_attrs,
+ dask="allowed",
+ )
+
def __enter__(self: T) -> T:
return self
diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py
index 3d192882..7b28d396 100644
--- a/xarray/core/duck_array_ops.py
+++ b/xarray/core/duck_array_ops.py
@@ -149,6 +149,33 @@ masked_invalid = _dask_or_eager_func(
)
+def astype(data, **kwargs):
+ try:
+ return data.astype(**kwargs)
+ except TypeError as e:
+ # FIXME: This should no longer be necessary in future versions of sparse
+ # Current versions of sparse (v0.10.0) don't support the "casting" kwarg
+ # This was fixed by https://github.com/pydata/sparse/pull/392
+ try:
+ import sparse
+ except ImportError:
+ sparse = None
+ if (
+ "got an unexpected keyword argument 'casting'" in repr(e)
+ and sparse is not None
+ and isinstance(data, sparse._coo.core.COO)
+ ):
+ warnings.warn(
+ "The current version of sparse does not support the 'casting' argument. It will be ignored in the call to astype().",
+ RuntimeWarning,
+ stacklevel=4,
+ )
+ kwargs.pop("casting")
+ else:
+ raise e
+ return data.astype(**kwargs)
+
+
def asarray(data, xp=np):
return (
data
diff --git a/xarray/core/ops.py b/xarray/core/ops.py
index 36753179..dad37f3b 100644
--- a/xarray/core/ops.py
+++ b/xarray/core/ops.py
@@ -42,7 +42,7 @@ NUM_BINARY_OPS = [
NUMPY_SAME_METHODS = ["item", "searchsorted"]
# methods which don't modify the data shape, so the result should still be
# wrapped in an Variable/DataArray
-NUMPY_UNARY_METHODS = ["astype", "argsort", "clip", "conj", "conjugate"]
+NUMPY_UNARY_METHODS = ["argsort", "clip", "conj", "conjugate"]
PANDAS_UNARY_FUNCTIONS = ["isnull", "notnull"]
# methods which remove an axis
REDUCE_METHODS = ["all", "any"]
diff --git a/xarray/core/variable.py b/xarray/core/variable.py
index 1f86a403..6d53a4fe 100644
--- a/xarray/core/variable.py
+++ b/xarray/core/variable.py
@@ -360,6 +360,47 @@ class Variable(
)
self._data = data
+ def astype(self, dtype, casting="unsafe", copy=True, keep_attrs=True):
+ """
+ Copy of the Variable object, with data cast to a specified type.
+
+ Parameters
+ ----------
+ dtype : str or dtype
+ Typecode or data-type to which the array is cast.
+ casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
+ Controls what kind of data casting may occur. Defaults to 'unsafe'
+ for backwards compatibility.
+
+ * 'no' means the data types should not be cast at all.
+ * 'equiv' means only byte-order changes are allowed.
+ * 'safe' means only casts which can preserve values are allowed.
+ * 'same_kind' means only safe casts or casts within a kind,
+ like float64 to float32, are allowed.
+ * 'unsafe' means any data conversions may be done.
+ copy : bool, optional
+ By default, astype always returns a newly allocated array. If this
+ is set to False and the `dtype` requirement is satisfied, the input
+ array is returned instead of a copy.
+ keep_attrs : bool, optional
+ By default, astype keeps attributes. Set to False to remove
+ attributes in the returned object.
+
+ See also
+ --------
+ np.ndarray.astype
+ dask.array.Array.astype
+ """
+ from .computation import apply_ufunc
+
+ return apply_ufunc(
+ duck_array_ops.astype,
+ self,
+ kwargs=dict(dtype=dtype, casting=casting, copy=copy),
+ keep_attrs=keep_attrs,
+ dask="allowed",
+ )
+
def load(self, **kwargs):
"""Manually trigger loading of this variable's data from disk or a
remote source into memory and return this variable.
diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py
index f10404d7..77969e5c 100644
--- a/xarray/tests/test_dataarray.py
+++ b/xarray/tests/test_dataarray.py
@@ -1874,6 +1874,19 @@ class TestDataArray:
bar = Variable(["x", "y"], np.zeros((10, 20)))
assert_equal(self.dv, np.maximum(self.dv, bar))
+ def test_astype_attrs(self):
+ for v in [self.va.copy(), self.mda.copy(), self.ds.copy()]:
+ v.attrs["foo"] = "bar"
+ assert list(v.attrs.items()) == list(v.astype(float).attrs.items())
+ assert [] == list(v.astype(float, keep_attrs=False).attrs.items())
+
+ def test_astype_dtype(self):
+ original = DataArray([-1, 1, 2, 3, 1000])
+ converted = original.astype(float)
+ assert_array_equal(original, converted)
+ assert np.issubdtype(original.dtype, np.integer)
+ assert np.issubdtype(converted.dtype, np.floating)
+
def test_is_null(self):
x = np.random.RandomState(42).randn(5, 6)
x[x < 0] = np.nan
diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py
index da7621dc..9a95eb24 100644
--- a/xarray/tests/test_dataset.py
+++ b/xarray/tests/test_dataset.py
@@ -5607,6 +5607,17 @@ class TestDataset:
np.testing.assert_equal(padded["var1"].isel(dim2=[0, -1]).data, 42)
np.testing.assert_equal(padded["dim2"][[0, -1]].data, np.nan)
+ def test_astype_attrs(self):
+ data = create_test_data(seed=123)
+ data.attrs["foo"] = "bar"
+
+ assert list(data.attrs.items()) == list(data.astype(float).attrs.items())
+ assert list(data.var1.attrs.items()) == list(
+ data.astype(float).var1.attrs.items()
+ )
+ assert [] == list(data.astype(float, keep_attrs=False).attrs.items())
+ assert [] == list(data.astype(float, keep_attrs=False).var1.attrs.items())
+
# Py.test tests
```
|
{ "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 | |
672295017 | https://github.com/pydata/xarray/pull/4314#issuecomment-672295017 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY3MjI5NTAxNw== | max-sixty 5635139 | 2020-08-11T21:45:01Z | 2020-08-11T21:45:01Z | MEMBER | Great — I think this looks good — any final thoughts? |
{ "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 | |
670248276 | https://github.com/pydata/xarray/pull/4314#issuecomment-670248276 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY3MDI0ODI3Ng== | max-sixty 5635139 | 2020-08-06T23:59:16Z | 2020-08-06T23:59:16Z | MEMBER | I'm fine with reraising — though I think we should reraise, otherwise isn't it a confusing message? The try-expect is probably fine given the narrowness (very open to holding too low a standard tho); one step up would be checking it is a spare array. |
{ "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 | |
670157140 | https://github.com/pydata/xarray/pull/4314#issuecomment-670157140 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY3MDE1NzE0MA== | max-sixty 5635139 | 2020-08-06T19:46:25Z | 2020-08-06T19:46:25Z | MEMBER | For sure — good idea to defer to numpy rather than raise — should we do that only on existing versions though? Otherwise we won't roll over to the new version when they do release their next version? (the version check can be a single line, there are lots of examples in the repo, lmk if that's not clear) |
{ "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 | |
670095439 | https://github.com/pydata/xarray/pull/4314#issuecomment-670095439 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY3MDA5NTQzOQ== | max-sixty 5635139 | 2020-08-06T18:18:27Z | 2020-08-06T18:18:27Z | MEMBER | What do you think about reraising the error with a message about upgrading? Is this a narrow enough use case that we can avoid backward-compat fix in xarray? |
{ "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 | |
669610153 | https://github.com/pydata/xarray/pull/4314#issuecomment-669610153 | https://api.github.com/repos/pydata/xarray/issues/4314 | MDEyOklzc3VlQ29tbWVudDY2OTYxMDE1Mw== | max-sixty 5635139 | 2020-08-06T00:16:33Z | 2020-08-06T00:16:33Z | MEMBER | I'm not sure re the test at first glance, I don't see how those tests are related, but master seems to pass. I pushed a merge to master as a check — hope that's OK. Let's see if that sheds any light |
{ "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0 } |
Recreate @gajomi's #2070 to keep attrs when calling astype() 673757961 |
Advanced export
JSON shape: default, array, newline-delimited, object
CREATE TABLE [issue_comments] ( [html_url] TEXT, [issue_url] TEXT, [id] INTEGER PRIMARY KEY, [node_id] TEXT, [user] INTEGER REFERENCES [users]([id]), [created_at] TEXT, [updated_at] TEXT, [author_association] TEXT, [body] TEXT, [reactions] TEXT, [performed_via_github_app] TEXT, [issue] INTEGER REFERENCES [issues]([id]) ); CREATE INDEX [idx_issue_comments_issue] ON [issue_comments] ([issue]); CREATE INDEX [idx_issue_comments_user] ON [issue_comments] ([user]);
user 1