@@ -1219,25 +1219,57 @@ def _wrap_applied_output(self, keys, values, not_indexed_same=False):
1219
1219
if len (keys ) == 0 :
1220
1220
return self .obj ._constructor (index = keys )
1221
1221
1222
+ key_names = self .grouper .names
1223
+
1222
1224
# GH12824
1223
1225
first_not_none = next (com .not_none (* values ), None )
1224
1226
1225
1227
if first_not_none is None :
1226
- # GH9684 - All values are None, return an empty frame.
1228
+ # GH9684. If all values are None, then this will throw an error.
1229
+ # We'd prefer it return an empty dataframe.
1227
1230
return self .obj ._constructor ()
1228
1231
elif isinstance (first_not_none , DataFrame ):
1229
1232
return self ._concat_objects (keys , values , not_indexed_same = not_indexed_same )
1230
1233
else :
1231
- key_index = self .grouper .result_index if self .as_index else None
1234
+ if len (self .grouper .groupings ) > 1 :
1235
+ key_index = self .grouper .result_index
1236
+
1237
+ else :
1238
+ ping = self .grouper .groupings [0 ]
1239
+ if len (keys ) == ping .ngroups :
1240
+ key_index = ping .group_index
1241
+ key_index .name = key_names [0 ]
1242
+
1243
+ key_lookup = Index (keys )
1244
+ indexer = key_lookup .get_indexer (key_index )
1245
+
1246
+ # reorder the values
1247
+ values = [values [i ] for i in indexer ]
1248
+
1249
+ # update due to the potential reorder
1250
+ first_not_none = next (com .not_none (* values ), None )
1251
+ else :
1252
+
1253
+ key_index = Index (keys , name = key_names [0 ])
1254
+
1255
+ # don't use the key indexer
1256
+ if not self .as_index :
1257
+ key_index = None
1232
1258
1233
- if isinstance (first_not_none , Series ):
1259
+ # make Nones an empty object
1260
+ if first_not_none is None :
1261
+ return self .obj ._constructor ()
1262
+ elif isinstance (first_not_none , NDFrame ):
1234
1263
1235
1264
# this is to silence a DeprecationWarning
1236
1265
# TODO: Remove when default dtype of empty Series is object
1237
1266
kwargs = first_not_none ._construct_axes_dict ()
1238
- backup = create_series_with_explicit_dtype (
1239
- ** kwargs , dtype_if_empty = object
1240
- )
1267
+ if isinstance (first_not_none , Series ):
1268
+ backup = create_series_with_explicit_dtype (
1269
+ ** kwargs , dtype_if_empty = object
1270
+ )
1271
+ else :
1272
+ backup = first_not_none ._constructor (** kwargs )
1241
1273
1242
1274
values = [x if (x is not None ) else backup for x in values ]
1243
1275
@@ -1246,7 +1278,7 @@ def _wrap_applied_output(self, keys, values, not_indexed_same=False):
1246
1278
if isinstance (v , (np .ndarray , Index , Series )) or not self .as_index :
1247
1279
if isinstance (v , Series ):
1248
1280
applied_index = self ._selected_obj ._get_axis (self .axis )
1249
- all_indexed_same = all_indexes_same (( x .index for x in values ) )
1281
+ all_indexed_same = all_indexes_same ([ x .index for x in values ] )
1250
1282
singular_series = len (values ) == 1 and applied_index .nlevels == 1
1251
1283
1252
1284
# GH3596
@@ -1278,6 +1310,7 @@ def _wrap_applied_output(self, keys, values, not_indexed_same=False):
1278
1310
# GH 8467
1279
1311
return self ._concat_objects (keys , values , not_indexed_same = True )
1280
1312
1313
+ if self .axis == 0 and isinstance (v , ABCSeries ):
1281
1314
# GH6124 if the list of Series have a consistent name,
1282
1315
# then propagate that name to the result.
1283
1316
index = v .index .copy ()
@@ -1290,27 +1323,34 @@ def _wrap_applied_output(self, keys, values, not_indexed_same=False):
1290
1323
if len (names ) == 1 :
1291
1324
index .name = list (names )[0 ]
1292
1325
1293
- # Combine values
1294
- # vstack+constructor is faster than concat and handles MI-columns
1295
- stacked_values = np .vstack ([np .asarray (v ) for v in values ])
1296
-
1297
- if self .axis == 0 :
1298
- index = key_index
1299
- columns = v .index .copy ()
1300
- if columns .name is None :
1301
- # GH6124 - propagate name of Series when it's consistent
1302
- names = {v .name for v in values }
1303
- if len (names ) == 1 :
1304
- columns .name = list (names )[0 ]
1326
+ # normally use vstack as its faster than concat
1327
+ # and if we have mi-columns
1328
+ if (
1329
+ isinstance (v .index , MultiIndex )
1330
+ or key_index is None
1331
+ or isinstance (key_index , MultiIndex )
1332
+ ):
1333
+ stacked_values = np .vstack ([np .asarray (v ) for v in values ])
1334
+ result = self .obj ._constructor (
1335
+ stacked_values , index = key_index , columns = index
1336
+ )
1305
1337
else :
1306
- index = v .index
1307
- columns = key_index
1308
- stacked_values = stacked_values .T
1309
-
1338
+ # GH5788 instead of stacking; concat gets the
1339
+ # dtypes correct
1340
+ from pandas .core .reshape .concat import concat
1341
+
1342
+ result = concat (
1343
+ values ,
1344
+ keys = key_index ,
1345
+ names = key_index .names ,
1346
+ axis = self .axis ,
1347
+ ).unstack ()
1348
+ result .columns = index
1349
+ elif isinstance (v , ABCSeries ):
1350
+ stacked_values = np .vstack ([np .asarray (v ) for v in values ])
1310
1351
result = self .obj ._constructor (
1311
- stacked_values , index = index , columns = columns
1352
+ stacked_values . T , index = v . index , columns = key_index
1312
1353
)
1313
-
1314
1354
elif not self .as_index :
1315
1355
# We add grouping column below, so create a frame here
1316
1356
result = DataFrame (
0 commit comments