@@ -3234,14 +3234,15 @@ def diff(self, periods=1):
3234
3234
#----------------------------------------------------------------------
3235
3235
# Function application
3236
3236
3237
- def apply (self , func , axis = 0 , broadcast = False , raw = False , reduce = True ,
3237
+ def apply (self , func , axis = 0 , broadcast = False , raw = False , reduce = None ,
3238
3238
args = (), ** kwds ):
3239
3239
"""
3240
3240
Applies function along input axis of DataFrame.
3241
3241
3242
3242
Objects passed to functions are Series objects having index
3243
3243
either the DataFrame's index (axis=0) or the columns (axis=1).
3244
- Return type depends on whether passed function aggregates
3244
+ Return type depends on whether passed function aggregates, or the
3245
+ reduce argument if the DataFrame is empty.
3245
3246
3246
3247
Parameters
3247
3248
----------
@@ -3253,8 +3254,14 @@ def apply(self, func, axis=0, broadcast=False, raw=False, reduce=True,
3253
3254
broadcast : boolean, default False
3254
3255
For aggregation functions, return object of same size with values
3255
3256
propagated
3256
- reduce : boolean, default True
3257
- Try to apply reduction procedures
3257
+ reduce : boolean or None, default None
3258
+ Try to apply reduction procedures. If the DataFrame is empty,
3259
+ apply will use reduce to determine whether the result should be a
3260
+ Series or a DataFrame. If reduce is None (the default), apply's
3261
+ return value will be guessed by calling func an empty Series (note:
3262
+ while guessing, exceptions raised by func will be ignored). If
3263
+ reduce is True a Series will always be returned, and if False a
3264
+ DataFrame will always be returned.
3258
3265
raw : boolean, default False
3259
3266
If False, convert each row or column into a Series. If raw=True the
3260
3267
passed function will receive ndarray objects instead. If you are
@@ -3279,41 +3286,46 @@ def apply(self, func, axis=0, broadcast=False, raw=False, reduce=True,
3279
3286
-------
3280
3287
applied : Series or DataFrame
3281
3288
"""
3282
- if len (self .columns ) == 0 and len (self .index ) == 0 :
3283
- return self
3284
-
3285
3289
axis = self ._get_axis_number (axis )
3286
3290
if kwds or args and not isinstance (func , np .ufunc ):
3287
3291
f = lambda x : func (x , * args , ** kwds )
3288
3292
else :
3289
3293
f = func
3290
3294
3295
+ if len (self .columns ) == 0 and len (self .index ) == 0 :
3296
+ return self ._apply_empty_result (func , axis , reduce )
3297
+
3291
3298
if isinstance (f , np .ufunc ):
3292
3299
results = f (self .values )
3293
3300
return self ._constructor (data = results , index = self .index ,
3294
3301
columns = self .columns , copy = False )
3295
3302
else :
3296
3303
if not broadcast :
3297
3304
if not all (self .shape ):
3298
- # How to determine this better?
3299
- is_reduction = False
3300
- try :
3301
- is_reduction = not isinstance (f (_EMPTY_SERIES ), Series )
3302
- except Exception :
3303
- pass
3304
-
3305
- if is_reduction :
3306
- return Series (NA , index = self ._get_agg_axis (axis ))
3307
- else :
3308
- return self .copy ()
3305
+ return self ._apply_empty_result (func , axis , reduce )
3309
3306
3310
3307
if raw and not self ._is_mixed_type :
3311
3308
return self ._apply_raw (f , axis )
3312
3309
else :
3310
+ if reduce is None :
3311
+ reduce = True
3313
3312
return self ._apply_standard (f , axis , reduce = reduce )
3314
3313
else :
3315
3314
return self ._apply_broadcast (f , axis )
3316
3315
3316
+ def _apply_empty_result (self , func , axis , reduce ):
3317
+ if reduce is None :
3318
+ reduce = False
3319
+ try :
3320
+ reduce = not isinstance (func (_EMPTY_SERIES ), Series )
3321
+ except Exception :
3322
+ pass
3323
+
3324
+ if reduce :
3325
+ return Series (NA , index = self ._get_agg_axis (axis ))
3326
+ else :
3327
+ return self .copy ()
3328
+
3317
3329
def _apply_raw (self , func , axis ):
3318
3330
try :
3319
3331
result = lib .reduce (self .values , func , axis = axis )
0 commit comments