Skip to content
forked from pydata/xarray

Commit 740b217

Browse files
committed
Merge remote-tracking branch 'upstream/master' into fix/whats-new
* upstream/master: Added fill_value for unstack (pydata#3541)
2 parents 233d7a8 + 56c16e4 commit 740b217

File tree

4 files changed

+36
-6
lines changed

4 files changed

+36
-6
lines changed

doc/whats-new.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ New Features
4040

4141
- Added the ``max_gap`` kwarg to :py:meth:`DataArray.interpolate_na` and
4242
:py:meth:`Dataset.interpolate_na`. This controls the maximum size of the data
43+
- Added the ``fill_value`` option to :py:meth:`~xarray.DataArray.unstack` and
44+
:py:meth:`~xarray.Dataset.unstack` (:issue:`3518`).
45+
By `Keisuke Fujii <https://github.com/fujiisoup>`_.
46+
- Added the ``max_gap`` kwarg to :py:meth:`~xarray.DataArray.interpolate_na` and
47+
:py:meth:`~xarray.Dataset.interpolate_na`. This controls the maximum size of the data
4348
gap that will be filled by interpolation. By `Deepak Cherian <https://github.com/dcherian>`_.
4449
- :py:meth:`Dataset.drop_sel` & :py:meth:`DataArray.drop_sel` have been added for dropping labels.
4550
:py:meth:`Dataset.drop_vars` & :py:meth:`DataArray.drop_vars` have been added for

xarray/core/dataarray.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,9 @@ def stack(
17261726
return self._from_temp_dataset(ds)
17271727

17281728
def unstack(
1729-
self, dim: Union[Hashable, Sequence[Hashable], None] = None
1729+
self,
1730+
dim: Union[Hashable, Sequence[Hashable], None] = None,
1731+
fill_value: Any = dtypes.NA,
17301732
) -> "DataArray":
17311733
"""
17321734
Unstack existing dimensions corresponding to MultiIndexes into
@@ -1739,6 +1741,7 @@ def unstack(
17391741
dim : hashable or sequence of hashable, optional
17401742
Dimension(s) over which to unstack. By default unstacks all
17411743
MultiIndexes.
1744+
fill_value: value to be filled. By default, np.nan
17421745
17431746
Returns
17441747
-------
@@ -1770,7 +1773,7 @@ def unstack(
17701773
--------
17711774
DataArray.stack
17721775
"""
1773-
ds = self._to_temp_dataset().unstack(dim)
1776+
ds = self._to_temp_dataset().unstack(dim, fill_value)
17741777
return self._from_temp_dataset(ds)
17751778

17761779
def to_unstacked_dataset(self, dim, level=0):

xarray/core/dataset.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3333,7 +3333,7 @@ def ensure_stackable(val):
33333333

33343334
return data_array
33353335

3336-
def _unstack_once(self, dim: Hashable) -> "Dataset":
3336+
def _unstack_once(self, dim: Hashable, fill_value) -> "Dataset":
33373337
index = self.get_index(dim)
33383338
index = index.remove_unused_levels()
33393339
full_idx = pd.MultiIndex.from_product(index.levels, names=index.names)
@@ -3342,7 +3342,7 @@ def _unstack_once(self, dim: Hashable) -> "Dataset":
33423342
if index.equals(full_idx):
33433343
obj = self
33443344
else:
3345-
obj = self.reindex({dim: full_idx}, copy=False)
3345+
obj = self.reindex({dim: full_idx}, copy=False, fill_value=fill_value)
33463346

33473347
new_dim_names = index.names
33483348
new_dim_sizes = [lev.size for lev in index.levels]
@@ -3368,7 +3368,11 @@ def _unstack_once(self, dim: Hashable) -> "Dataset":
33683368
variables, coord_names=coord_names, indexes=indexes
33693369
)
33703370

3371-
def unstack(self, dim: Union[Hashable, Iterable[Hashable]] = None) -> "Dataset":
3371+
def unstack(
3372+
self,
3373+
dim: Union[Hashable, Iterable[Hashable]] = None,
3374+
fill_value: Any = dtypes.NA,
3375+
) -> "Dataset":
33723376
"""
33733377
Unstack existing dimensions corresponding to MultiIndexes into
33743378
multiple new dimensions.
@@ -3380,6 +3384,7 @@ def unstack(self, dim: Union[Hashable, Iterable[Hashable]] = None) -> "Dataset":
33803384
dim : Hashable or iterable of Hashable, optional
33813385
Dimension(s) over which to unstack. By default unstacks all
33823386
MultiIndexes.
3387+
fill_value: value to be filled. By default, np.nan
33833388
33843389
Returns
33853390
-------
@@ -3417,7 +3422,7 @@ def unstack(self, dim: Union[Hashable, Iterable[Hashable]] = None) -> "Dataset":
34173422

34183423
result = self.copy(deep=False)
34193424
for dim in dims:
3420-
result = result._unstack_once(dim)
3425+
result = result._unstack_once(dim, fill_value)
34213426
return result
34223427

34233428
def update(self, other: "CoercibleMapping", inplace: bool = None) -> "Dataset":

xarray/tests/test_dataset.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2794,6 +2794,23 @@ def test_unstack_errors(self):
27942794
with raises_regex(ValueError, "do not have a MultiIndex"):
27952795
ds.unstack("x")
27962796

2797+
def test_unstack_fill_value(self):
2798+
ds = xr.Dataset(
2799+
{"var": (("x",), np.arange(6))},
2800+
coords={"x": [0, 1, 2] * 2, "y": (("x",), ["a"] * 3 + ["b"] * 3)},
2801+
)
2802+
# make ds incomplete
2803+
ds = ds.isel(x=[0, 2, 3, 4]).set_index(index=["x", "y"])
2804+
# test fill_value
2805+
actual = ds.unstack("index", fill_value=-1)
2806+
expected = ds.unstack("index").fillna(-1).astype(np.int)
2807+
assert actual["var"].dtype == np.int
2808+
assert_equal(actual, expected)
2809+
2810+
actual = ds["var"].unstack("index", fill_value=-1)
2811+
expected = ds["var"].unstack("index").fillna(-1).astype(np.int)
2812+
assert actual.equals(expected)
2813+
27972814
def test_stack_unstack_fast(self):
27982815
ds = Dataset(
27992816
{

0 commit comments

Comments
 (0)