Unstacks this variable given an index to unstack and the name of the dimension to which the index refers.
(
self,
index: pd.MultiIndex,
dim: Hashable,
fill_value=dtypes.NA,
sparse: bool = False,
)
| 1597 | ) |
| 1598 | |
| 1599 | def _unstack_once( |
| 1600 | self, |
| 1601 | index: pd.MultiIndex, |
| 1602 | dim: Hashable, |
| 1603 | fill_value=dtypes.NA, |
| 1604 | sparse: bool = False, |
| 1605 | ) -> Variable: |
| 1606 | """ |
| 1607 | Unstacks this variable given an index to unstack and the name of the |
| 1608 | dimension to which the index refers. |
| 1609 | """ |
| 1610 | |
| 1611 | reordered = self.transpose(..., dim) |
| 1612 | |
| 1613 | new_dim_sizes = [lev.size for lev in index.levels] |
| 1614 | new_dim_names = index.names |
| 1615 | indexer = index.codes |
| 1616 | |
| 1617 | # Potentially we could replace `len(other_dims)` with just `-1` |
| 1618 | other_dims = [d for d in self.dims if d != dim] |
| 1619 | new_shape = tuple(list(reordered.shape[: len(other_dims)]) + new_dim_sizes) |
| 1620 | new_dims = reordered.dims[: len(other_dims)] + tuple(new_dim_names) |
| 1621 | |
| 1622 | create_template: Callable |
| 1623 | if fill_value is dtypes.NA: |
| 1624 | is_missing_values = math.prod(new_shape) > math.prod(self.shape) |
| 1625 | if is_missing_values: |
| 1626 | dtype, fill_value = dtypes.maybe_promote(self.dtype) |
| 1627 | |
| 1628 | create_template = partial( |
| 1629 | duck_array_ops.full_like, fill_value=fill_value |
| 1630 | ) |
| 1631 | else: |
| 1632 | dtype = self.dtype |
| 1633 | fill_value = dtypes.get_fill_value(dtype) |
| 1634 | create_template = duck_array_ops.empty_like |
| 1635 | else: |
| 1636 | dtype = self.dtype |
| 1637 | create_template = partial(duck_array_ops.full_like, fill_value=fill_value) |
| 1638 | |
| 1639 | if sparse: |
| 1640 | # unstacking a dense multitindexed array to a sparse array |
| 1641 | from sparse import COO |
| 1642 | |
| 1643 | codes = zip(*index.codes, strict=True) |
| 1644 | if reordered.ndim == 1: |
| 1645 | indexes = codes |
| 1646 | else: |
| 1647 | sizes = itertools.product(*[range(s) for s in reordered.shape[:-1]]) |
| 1648 | tuple_indexes = itertools.product(sizes, codes) |
| 1649 | indexes = (list(itertools.chain(*x)) for x in tuple_indexes) # type: ignore[assignment] |
| 1650 | |
| 1651 | data = COO( |
| 1652 | coords=np.array(list(indexes)).T, |
| 1653 | data=self.data.astype(dtype).ravel(), |
| 1654 | fill_value=fill_value, |
| 1655 | shape=new_shape, |
| 1656 | sorted=index.is_monotonic_increasing, |
nothing calls this directly
no test coverage detected