@@ -95,7 +95,7 @@ def _groupby_function(name, alias, npfunc, numeric_only=True,
95
95
@Appender (_doc_template )
96
96
@Appender (_local_template )
97
97
def f (self ):
98
- self ._set_selection_from_grouper ()
98
+ self ._set_group_selection ()
99
99
try :
100
100
return self ._cython_agg_general (alias , numeric_only = numeric_only )
101
101
except AssertionError as e :
@@ -457,8 +457,21 @@ def _selected_obj(self):
457
457
else :
458
458
return self .obj [self ._selection ]
459
459
460
- def _set_selection_from_grouper (self ):
461
- """ we may need create a selection if we have non-level groupers """
460
+ def _reset_group_selection (self ):
461
+ """
462
+ Clear group based selection. Used for methods needing to return info on
463
+ each group regardless of whether a group selection was previously set.
464
+ """
465
+ if self ._group_selection is not None :
466
+ self ._group_selection = None
467
+ # GH12839 clear cached selection too when changing group selection
468
+ self ._reset_cache ('_selected_obj' )
469
+
470
+ def _set_group_selection (self ):
471
+ """
472
+ Create group based selection. Used when selection is not passed
473
+ directly but instead via a grouper.
474
+ """
462
475
grp = self .grouper
463
476
if self .as_index and getattr (grp , 'groupings' , None ) is not None and \
464
477
self .obj .ndim > 1 :
@@ -468,6 +481,8 @@ def _set_selection_from_grouper(self):
468
481
469
482
if len (groupers ):
470
483
self ._group_selection = ax .difference (Index (groupers )).tolist ()
484
+ # GH12839 clear selected obj cache when group selection changes
485
+ self ._reset_cache ('_selected_obj' )
471
486
472
487
def _set_result_index_ordered (self , result ):
473
488
# set the result index on the passed values object and
@@ -511,7 +526,7 @@ def _make_wrapper(self, name):
511
526
512
527
# need to setup the selection
513
528
# as are not passed directly but in the grouper
514
- self ._set_selection_from_grouper ()
529
+ self ._set_group_selection ()
515
530
516
531
f = getattr (self ._selected_obj , name )
517
532
if not isinstance (f , types .MethodType ):
@@ -979,7 +994,7 @@ def mean(self, *args, **kwargs):
979
994
except GroupByError :
980
995
raise
981
996
except Exception : # pragma: no cover
982
- self ._set_selection_from_grouper ()
997
+ self ._set_group_selection ()
983
998
f = lambda x : x .mean (axis = self .axis )
984
999
return self ._python_agg_general (f )
985
1000
@@ -997,7 +1012,7 @@ def median(self):
997
1012
raise
998
1013
except Exception : # pragma: no cover
999
1014
1000
- self ._set_selection_from_grouper ()
1015
+ self ._set_group_selection ()
1001
1016
1002
1017
def f (x ):
1003
1018
if isinstance (x , np .ndarray ):
@@ -1040,7 +1055,7 @@ def var(self, ddof=1, *args, **kwargs):
1040
1055
if ddof == 1 :
1041
1056
return self ._cython_agg_general ('var' )
1042
1057
else :
1043
- self ._set_selection_from_grouper ()
1058
+ self ._set_group_selection ()
1044
1059
f = lambda x : x .var (ddof = ddof )
1045
1060
return self ._python_agg_general (f )
1046
1061
@@ -1217,7 +1232,7 @@ def nth(self, n, dropna=None):
1217
1232
raise TypeError ("n needs to be an int or a list/set/tuple of ints" )
1218
1233
1219
1234
nth_values = np .array (nth_values , dtype = np .intp )
1220
- self ._set_selection_from_grouper ()
1235
+ self ._set_group_selection ()
1221
1236
1222
1237
if not dropna :
1223
1238
mask = np .in1d (self ._cumcount_array (), nth_values ) | \
@@ -1325,7 +1340,7 @@ def cumcount(self, ascending=True):
1325
1340
dtype: int64
1326
1341
"""
1327
1342
1328
- self ._set_selection_from_grouper ()
1343
+ self ._set_group_selection ()
1329
1344
1330
1345
index = self ._selected_obj .index
1331
1346
cumcounts = self ._cumcount_array (ascending = ascending )
@@ -1403,6 +1418,7 @@ def head(self, n=5):
1403
1418
0 1 2
1404
1419
2 5 6
1405
1420
"""
1421
+ self ._reset_group_selection ()
1406
1422
mask = self ._cumcount_array () < n
1407
1423
return self ._selected_obj [mask ]
1408
1424
@@ -1429,6 +1445,7 @@ def tail(self, n=5):
1429
1445
0 a 1
1430
1446
2 b 1
1431
1447
"""
1448
+ self ._reset_group_selection ()
1432
1449
mask = self ._cumcount_array (ascending = False ) < n
1433
1450
return self ._selected_obj [mask ]
1434
1451
0 commit comments