@@ -37,8 +37,22 @@ class _Unstacker(object):
37
37
38
38
Parameters
39
39
----------
40
+ values : ndarray
41
+ Values of DataFrame to "Unstack"
42
+ index : object
43
+ Pandas ``Index``
40
44
level : int or str, default last level
41
45
Level to "unstack". Accepts a name for the level.
46
+ value_columns : Index, optional
47
+ Pandas ``Index`` or ``MultiIndex`` object if unstacking a DataFrame
48
+ fill_value : scalar, optional
49
+ Default value to fill in missing values if subgroups do not have the
50
+ same set of labels. By default, missing values will be replaced with
51
+ the default fill value for that data type, NaN for float, NaT for
52
+ datetimelike, etc. For integer types, by default data will converted to
53
+ float and missing values will be set to NaN.
54
+ obj : Series, DataFrame
55
+ Object that is being unstacked (also used to get subclass)
42
56
43
57
Examples
44
58
--------
@@ -68,8 +82,12 @@ class _Unstacker(object):
68
82
unstacked : DataFrame
69
83
"""
70
84
71
- def __init__ (self , values , index , level = - 1 , value_columns = None ,
72
- fill_value = None ):
85
+ def __init__ (self , values = None , index = None , level = - 1 , value_columns = None ,
86
+ fill_value = None , obj = None ):
87
+
88
+ if obj is not None :
89
+ values = obj .values
90
+ index = obj .index
73
91
74
92
self .is_categorical = None
75
93
self .is_sparse = is_sparse (values )
@@ -85,6 +103,7 @@ def __init__(self, values, index, level=-1, value_columns=None,
85
103
self .values = values
86
104
self .value_columns = value_columns
87
105
self .fill_value = fill_value
106
+ self .obj = obj
88
107
89
108
if value_columns is None and values .shape [1 ] != 1 : # pragma: no cover
90
109
raise ValueError ('must pass column labels for multi-column data' )
@@ -173,8 +192,11 @@ def get_result(self):
173
192
ordered = ordered )
174
193
for i in range (values .shape [- 1 ])]
175
194
176
- klass = SparseDataFrame if self .is_sparse else DataFrame
177
- return klass (values , index = index , columns = columns )
195
+ if isinstance (self .obj , Series ):
196
+ constructor = self .obj ._constructor_expanddim
197
+ else :
198
+ constructor = self .obj ._constructor
199
+ return constructor (values , index = index , columns = columns )
178
200
179
201
def get_new_values (self ):
180
202
values = self .values
@@ -374,8 +396,9 @@ def pivot(self, index=None, columns=None, values=None):
374
396
index = self .index
375
397
else :
376
398
index = self [index ]
377
- indexed = Series (self [values ].values ,
378
- index = MultiIndex .from_arrays ([index , self [columns ]]))
399
+ indexed = self ._constructor_sliced (
400
+ self [values ].values ,
401
+ index = MultiIndex .from_arrays ([index , self [columns ]]))
379
402
return indexed .unstack (columns )
380
403
381
404
@@ -460,7 +483,7 @@ def unstack(obj, level, fill_value=None):
460
483
else :
461
484
return obj .T .stack (dropna = False )
462
485
else :
463
- unstacker = _Unstacker (obj . values , obj . index , level = level ,
486
+ unstacker = _Unstacker (obj = obj , level = level ,
464
487
fill_value = fill_value )
465
488
return unstacker .get_result ()
466
489
@@ -470,10 +493,9 @@ def _unstack_frame(obj, level, fill_value=None):
470
493
unstacker = partial (_Unstacker , index = obj .index ,
471
494
level = level , fill_value = fill_value )
472
495
blocks = obj ._data .unstack (unstacker )
473
- klass = type (obj )
474
- return klass (blocks )
496
+ return obj ._constructor (blocks )
475
497
else :
476
- unstacker = _Unstacker (obj . values , obj . index , level = level ,
498
+ unstacker = _Unstacker (obj = obj , level = level ,
477
499
value_columns = obj .columns ,
478
500
fill_value = fill_value )
479
501
return unstacker .get_result ()
@@ -528,8 +550,7 @@ def factorize(index):
528
550
new_values = new_values [mask ]
529
551
new_index = new_index [mask ]
530
552
531
- klass = type (frame )._constructor_sliced
532
- return klass (new_values , index = new_index )
553
+ return frame ._constructor_sliced (new_values , index = new_index )
533
554
534
555
535
556
def stack_multiple (frame , level , dropna = True ):
@@ -675,7 +696,7 @@ def _convert_level_number(level_num, columns):
675
696
new_index = MultiIndex (levels = new_levels , labels = new_labels ,
676
697
names = new_names , verify_integrity = False )
677
698
678
- result = DataFrame (new_data , index = new_index , columns = new_columns )
699
+ result = frame . _constructor (new_data , index = new_index , columns = new_columns )
679
700
680
701
# more efficient way to go about this? can do the whole masking biz but
681
702
# will only save a small amount of time...
0 commit comments