Skip to content
Closed
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
42 changes: 41 additions & 1 deletion xarray/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -773,10 +773,10 @@ def isin(self, test_elements):
--------
numpy.isin
"""
from .computation import apply_ufunc
from .dataset import Dataset
from .dataarray import DataArray
from .variable import Variable
from .computation import apply_ufunc

if isinstance(test_elements, Dataset):
raise TypeError(
Expand All @@ -794,6 +794,46 @@ def isin(self, test_elements):
dask='allowed',
)

def astype(self, dtype, casting = 'unsafe', copy = 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.

See also
--------
np.ndarray.astype
dask.array.Array.astype
"""
from .computation import apply_ufunc

return apply_ufunc(
duck_array_ops.astype,
self,
dtype,
keep_attrs=True,
kwargs={'casting':casting,'copy':copy},
dask='allowed'
)

def __enter__(self):
return self

Expand Down
3 changes: 3 additions & 0 deletions xarray/core/duck_array_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def isnull(data):
tensordot = _dask_or_eager_func('tensordot', n_array_args=2)


def astype(data, dtype, **kwargs):
return data.astype(dtype, **kwargs)

def asarray(data):
return data if isinstance(data, dask_array_type) else np.asarray(data)

Expand Down
2 changes: 1 addition & 1 deletion xarray/core/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
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']
Expand Down
34 changes: 34 additions & 0 deletions xarray/core/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,40 @@ def data(self, data):
"replacement data must match the Variable's shape")
self._data = data

def astype(self, dtype, casting = 'unsafe', copy = 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.

See also
--------
np.ndarray.astype
dask.array.Array.astype
"""
self.data = duck_array_ops.astype(self.data,
dtype,
casting = casting,
copy = copy)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E251 unexpected spaces around keyword / parameter equals

return self

def load(self, **kwargs):
"""Manually trigger loading of this variable's data from disk or a
remote source into memory and return this variable.
Expand Down
6 changes: 5 additions & 1 deletion xarray/tests/test_dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -1446,8 +1446,8 @@ def test_dataset_getitem(self):

def test_array_interface(self):
assert_array_equal(np.asarray(self.dv), self.x)
# test patched in methods
assert_array_equal(self.dv.astype(float), self.v.astype(float))
# test patched in methods
assert_array_equal(self.dv.argsort(), self.v.argsort())
assert_array_equal(self.dv.clip(2, 3), self.v.clip(2, 3))
# test ufuncs
Expand All @@ -1458,6 +1458,10 @@ def test_array_interface(self):
bar = Variable(['x', 'y'], np.zeros((10, 20)))
assert_equal(self.dv, np.maximum(self.dv, bar))

def test_astype_attrs(self):
mda = self.mda.astype(bool)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to test the datatype converting behavior of astype() here, too, at least with a few minimal cases. I don't know if we have test coverage for this already.

assert list(mda.attrs.items()) == list(self.mda.attrs.items())

def test_is_null(self):
x = np.random.RandomState(42).randn(5, 6)
x[x < 0] = np.nan
Expand Down
1 change: 0 additions & 1 deletion xarray/tests/test_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,6 @@ def test_array_interface(self):
x = np.arange(5)
v = self.cls(['x'], x)
assert_array_equal(np.asarray(v), x)
# test patched in methods
assert_array_equal(v.astype(float), x.astype(float))
# think this is a break, that argsort changes the type
assert_identical(v.argsort(), v.to_base_variable())
Expand Down