|
9 | 9 | from pandas.core.frame import DataFrame
|
10 | 10 |
|
11 | 11 | from pandas.core.common import notnull, _ensure_platform_int
|
12 |
| -from pandas.core.groupby import get_group_index |
| 12 | +from pandas.core.groupby import (get_group_index, _compress_group_index, |
| 13 | + decons_group_index) |
| 14 | + |
| 15 | + |
13 | 16 | from pandas.core.index import MultiIndex
|
14 | 17 |
|
15 | 18 |
|
@@ -198,6 +201,71 @@ def get_new_index(self):
|
198 | 201 | return new_index
|
199 | 202 |
|
200 | 203 |
|
| 204 | +def _unstack_multiple(data, clocs): |
| 205 | + if len(clocs) == 0: |
| 206 | + return data |
| 207 | + |
| 208 | + # NOTE: This doesn't deal with hierarchical columns yet |
| 209 | + |
| 210 | + index = data.index |
| 211 | + |
| 212 | + clevels, rlevels = _partition(index.levels, clocs) |
| 213 | + clabels, rlabels = _partition(index.labels, clocs) |
| 214 | + cnames, rnames = _partition(index.names, clocs) |
| 215 | + |
| 216 | + shape = [len(x) for x in clevels] |
| 217 | + group_index = get_group_index(clabels, shape) |
| 218 | + |
| 219 | + comp_ids, obs_ids = _compress_group_index(group_index, sort=False) |
| 220 | + |
| 221 | + dummy_index = MultiIndex(levels=rlevels + [obs_ids], |
| 222 | + labels=rlabels + [comp_ids], |
| 223 | + names=rnames + ['__placeholder__']) |
| 224 | + |
| 225 | + dummy = DataFrame(data.values, index=dummy_index, |
| 226 | + columns=data.columns) |
| 227 | + |
| 228 | + unstacked = dummy.unstack('__placeholder__') |
| 229 | + |
| 230 | + if isinstance(unstacked, Series): |
| 231 | + unstcols = unstacked.index |
| 232 | + else: |
| 233 | + unstcols = unstacked.columns |
| 234 | + |
| 235 | + new_levels = [unstcols.levels[0]] + clevels |
| 236 | + new_names = [data.columns.name] + cnames |
| 237 | + |
| 238 | + recons_labels = decons_group_index(obs_ids, shape) |
| 239 | + |
| 240 | + new_labels = [unstcols.labels[0]] |
| 241 | + for rec in recons_labels: |
| 242 | + new_labels.append(rec.take(unstcols.labels[-1])) |
| 243 | + |
| 244 | + new_columns = MultiIndex(levels=new_levels, labels=new_labels, |
| 245 | + names=new_names) |
| 246 | + |
| 247 | + if isinstance(unstacked, Series): |
| 248 | + unstacked.index = new_columns |
| 249 | + else: |
| 250 | + unstacked.columns = new_columns |
| 251 | + |
| 252 | + return unstacked |
| 253 | + |
| 254 | + |
| 255 | +def _partition(values, inds): |
| 256 | + left = [] |
| 257 | + right = [] |
| 258 | + |
| 259 | + set_inds = set(inds) |
| 260 | + |
| 261 | + for i, val in enumerate(values): |
| 262 | + if i in set_inds: |
| 263 | + left.append(val) |
| 264 | + else: |
| 265 | + right.append(val) |
| 266 | + |
| 267 | + return left, right |
| 268 | + |
201 | 269 |
|
202 | 270 | def pivot(self, index=None, columns=None, values=None):
|
203 | 271 | """
|
|
0 commit comments