|
56 | 56 |
|
57 | 57 | from pandas.core.index import Index, MultiIndex, _ensure_index
|
58 | 58 | from pandas.core.indexing import maybe_convert_indices, length_of_indexer
|
59 |
| -from pandas.core.categorical import Categorical, maybe_to_categorical |
| 59 | +from pandas.core.categorical import Categorical, _maybe_to_categorical |
60 | 60 | from pandas.core.indexes.datetimes import DatetimeIndex
|
61 | 61 | from pandas.io.formats.printing import pprint_thing
|
62 | 62 |
|
@@ -1484,6 +1484,35 @@ def equals(self, other):
|
1484 | 1484 | return False
|
1485 | 1485 | return array_equivalent(self.values, other.values)
|
1486 | 1486 |
|
| 1487 | + def _unstack(self, unstacker_func, new_columns): |
| 1488 | + """Return a list of unstacked blocks of self |
| 1489 | +
|
| 1490 | + Parameters |
| 1491 | + ---------- |
| 1492 | + unstacker_func : callable |
| 1493 | + Partially applied unstacker. |
| 1494 | + new_columns : Index |
| 1495 | + All columns of the unstacked BlockManager. |
| 1496 | +
|
| 1497 | + Returns |
| 1498 | + ------- |
| 1499 | + blocks : list of Block |
| 1500 | + New blocks of unstacked values. |
| 1501 | + mask : array_like of bool |
| 1502 | + The mask of columns of `blocks` we should keep. |
| 1503 | + """ |
| 1504 | + unstacker = unstacker_func(self.values.T) |
| 1505 | + new_items = unstacker.get_new_columns() |
| 1506 | + new_placement = new_columns.get_indexer(new_items) |
| 1507 | + new_values, mask = unstacker.get_new_values() |
| 1508 | + |
| 1509 | + mask = mask.any(0) |
| 1510 | + new_values = new_values.T[mask] |
| 1511 | + new_placement = new_placement[mask] |
| 1512 | + |
| 1513 | + blocks = [make_block(new_values, placement=new_placement)] |
| 1514 | + return blocks, mask |
| 1515 | + |
1487 | 1516 | def quantile(self, qs, interpolation='linear', axis=0, mgr=None):
|
1488 | 1517 | """
|
1489 | 1518 | compute the quantiles of the
|
@@ -1712,6 +1741,38 @@ def _slice(self, slicer):
|
1712 | 1741 | def _try_cast_result(self, result, dtype=None):
|
1713 | 1742 | return result
|
1714 | 1743 |
|
| 1744 | + def _unstack(self, unstacker_func, new_columns): |
| 1745 | + """Return a list of unstacked blocks of self |
| 1746 | +
|
| 1747 | + Parameters |
| 1748 | + ---------- |
| 1749 | + unstacker_func : callable |
| 1750 | + Partially applied unstacker. |
| 1751 | + new_columns : Index |
| 1752 | + All columns of the unstacked BlockManager. |
| 1753 | +
|
| 1754 | + Returns |
| 1755 | + ------- |
| 1756 | + blocks : list of Block |
| 1757 | + New blocks of unstacked values. |
| 1758 | + mask : array_like of bool |
| 1759 | + The mask of columns of `blocks` we should keep. |
| 1760 | + """ |
| 1761 | + # NonConsolidatable blocks can have a single item only, so we return |
| 1762 | + # one block per item |
| 1763 | + unstacker = unstacker_func(self.values.T) |
| 1764 | + new_items = unstacker.get_new_columns() |
| 1765 | + new_placement = new_columns.get_indexer(new_items) |
| 1766 | + new_values, mask = unstacker.get_new_values() |
| 1767 | + |
| 1768 | + mask = mask.any(0) |
| 1769 | + new_values = new_values.T[mask] |
| 1770 | + new_placement = new_placement[mask] |
| 1771 | + |
| 1772 | + blocks = [self.make_block_same_class(vals, [place]) |
| 1773 | + for vals, place in zip(new_values, new_placement)] |
| 1774 | + return blocks, mask |
| 1775 | + |
1715 | 1776 |
|
1716 | 1777 | class NumericBlock(Block):
|
1717 | 1778 | __slots__ = ()
|
@@ -2227,7 +2288,7 @@ class CategoricalBlock(NonConsolidatableMixIn, ObjectBlock):
|
2227 | 2288 | def __init__(self, values, placement, fastpath=False, **kwargs):
|
2228 | 2289 |
|
2229 | 2290 | # coerce to categorical if we can
|
2230 |
| - super(CategoricalBlock, self).__init__(maybe_to_categorical(values), |
| 2291 | + super(CategoricalBlock, self).__init__(_maybe_to_categorical(values), |
2231 | 2292 | fastpath=True,
|
2232 | 2293 | placement=placement, **kwargs)
|
2233 | 2294 |
|
@@ -4192,6 +4253,38 @@ def canonicalize(block):
|
4192 | 4253 | return all(block.equals(oblock)
|
4193 | 4254 | for block, oblock in zip(self_blocks, other_blocks))
|
4194 | 4255 |
|
| 4256 | + def unstack(self, unstacker_func): |
| 4257 | + """Return a blockmanager with all blocks unstacked. |
| 4258 | +
|
| 4259 | + Parameters |
| 4260 | + ---------- |
| 4261 | + unstacker_func : callable |
| 4262 | + A (partially-applied) ``pd.core.reshape._Unstacker`` class. |
| 4263 | +
|
| 4264 | + Returns |
| 4265 | + ------- |
| 4266 | + unstacked : BlockManager |
| 4267 | + """ |
| 4268 | + dummy = unstacker_func(np.empty((0, 0)), value_columns=self.items) |
| 4269 | + new_columns = dummy.get_new_columns() |
| 4270 | + new_index = dummy.get_new_index() |
| 4271 | + new_blocks = [] |
| 4272 | + columns_mask = [] |
| 4273 | + |
| 4274 | + for blk in self.blocks: |
| 4275 | + blocks, mask = blk._unstack( |
| 4276 | + partial(unstacker_func, |
| 4277 | + value_columns=self.items[blk.mgr_locs.indexer]), |
| 4278 | + new_columns) |
| 4279 | + |
| 4280 | + new_blocks.extend(blocks) |
| 4281 | + columns_mask.extend(mask) |
| 4282 | + |
| 4283 | + new_columns = new_columns[columns_mask] |
| 4284 | + |
| 4285 | + bm = BlockManager(new_blocks, [new_columns, new_index]) |
| 4286 | + return bm |
| 4287 | + |
4195 | 4288 |
|
4196 | 4289 | class SingleBlockManager(BlockManager):
|
4197 | 4290 | """ manage a single block with """
|
|
0 commit comments