@@ -114,27 +114,32 @@ def _make_selectors(self):
114
114
def get_result (self ):
115
115
# TODO: find a better way than this masking business
116
116
117
- values , mask = self .get_new_values ()
117
+ values , value_mask = self .get_new_values ()
118
118
columns = self .get_new_columns ()
119
119
index = self .get_new_index ()
120
120
121
121
# filter out missing levels
122
122
if values .shape [1 ] > 0 :
123
+ mask = value_mask .sum (0 ) > 0
123
124
values = values [:, mask ]
124
125
columns = columns [mask ]
125
126
126
127
return DataFrame (values , index = index , columns = columns )
127
128
128
129
def get_new_values (self ):
130
+ return self ._reshape_values (self .values )
131
+
132
+ def _reshape_values (self , values ):
133
+ values = self .values
129
134
# place the values
130
135
length , width = self .full_shape
131
- stride = self . values .shape [1 ]
136
+ stride = values .shape [1 ]
132
137
result_width = width * stride
133
138
134
- new_values = np .empty ((length , result_width ), dtype = self . values .dtype )
139
+ new_values = np .empty ((length , result_width ), dtype = values .dtype )
135
140
new_mask = np .zeros ((length , result_width ), dtype = bool )
136
141
137
- if issubclass (self . values .dtype .type , np .integer ):
142
+ if issubclass (values .dtype .type , np .integer ):
138
143
new_values = new_values .astype (float )
139
144
140
145
new_values .fill (np .nan )
@@ -148,7 +153,7 @@ def get_new_values(self):
148
153
mask_chunk .flat [self .mask ] = True
149
154
150
155
new_values = new_values .take (self .unique_groups , axis = 0 )
151
- return new_values , new_mask . sum ( 0 ) > 0
156
+ return new_values , new_mask
152
157
153
158
def get_new_columns (self ):
154
159
if self .value_columns is None :
@@ -284,12 +289,43 @@ def _slow_pivot(index, columns, values):
284
289
285
290
def unstack (obj , level ):
286
291
if isinstance (obj , DataFrame ):
287
- columns = obj .columns
292
+ return _unstack_frame (obj , level )
293
+ else :
294
+ unstacker = _Unstacker (obj .values , obj .index , level = level )
295
+ return unstacker .get_result ()
296
+
297
+ def _unstack_frame (obj , level ):
298
+ from pandas .core .internals import BlockManager , make_block
299
+
300
+ if obj ._is_mixed_type :
301
+ unstacker = _Unstacker (np .empty (obj .shape , dtype = bool ), # dummy
302
+ obj .index , level = level ,
303
+ value_columns = obj .columns )
304
+ new_columns = unstacker .get_new_columns ()
305
+ new_index = unstacker .get_new_index ()
306
+ new_axes = [new_columns , new_index ]
307
+
308
+ new_blocks = []
309
+ mask_blocks = []
310
+ for blk in obj ._data .blocks :
311
+ bunstacker = _Unstacker (blk .values .T , obj .index , level = level ,
312
+ value_columns = blk .items )
313
+ new_items = bunstacker .get_new_columns ()
314
+ new_values , mask = bunstacker .get_new_values ()
315
+
316
+ mblk = make_block (mask .T , new_items , new_columns )
317
+ mask_blocks .append (mblk )
318
+
319
+ newb = make_block (new_values .T , new_items , new_columns )
320
+ new_blocks .append (newb )
321
+
322
+ result = DataFrame (BlockManager (new_blocks , new_axes ))
323
+ mask_frame = DataFrame (BlockManager (mask_blocks , new_axes ))
324
+ return result .ix [:, mask_frame .sum (0 ) > 0 ]
288
325
else :
289
- columns = None
290
- unstacker = _Unstacker (obj .values , obj .index , level = level ,
291
- value_columns = columns )
292
- return unstacker .get_result ()
326
+ unstacker = _Unstacker (obj .values , obj .index , level = level ,
327
+ value_columns = obj .columns )
328
+ return unstacker .get_result ()
293
329
294
330
def stack (frame , level = - 1 , dropna = True ):
295
331
"""
0 commit comments