@@ -441,6 +441,9 @@ class Grouping:
441
441
442
442
_codes : np .ndarray | None = None
443
443
_group_index : Index | None = None
444
+ _passed_categorical : bool
445
+ _all_grouper : Categorical | None
446
+ _index : Index
444
447
445
448
def __init__ (
446
449
self ,
@@ -456,13 +459,13 @@ def __init__(
456
459
self .level = level
457
460
self ._orig_grouper = grouper
458
461
self .grouping_vector = _convert_grouper (index , grouper )
459
- self .all_grouper = None
460
- self .index = index
461
- self .sort = sort
462
+ self ._all_grouper = None
463
+ self ._index = index
464
+ self ._sort = sort
462
465
self .obj = obj
463
- self .observed = observed
466
+ self ._observed = observed
464
467
self .in_axis = in_axis
465
- self .dropna = dropna
468
+ self ._dropna = dropna
466
469
467
470
self ._passed_categorical = False
468
471
@@ -471,11 +474,15 @@ def __init__(
471
474
472
475
ilevel = self ._ilevel
473
476
if ilevel is not None :
477
+ mapper = self .grouping_vector
478
+ # In extant tests, the new self.grouping_vector matches
479
+ # `index.get_level_values(ilevel)` whenever
480
+ # mapper is None and isinstance(index, MultiIndex)
474
481
(
475
482
self .grouping_vector , # Index
476
483
self ._codes ,
477
484
self ._group_index ,
478
- ) = index ._get_grouper_for_level (self . grouping_vector , ilevel )
485
+ ) = index ._get_grouper_for_level (mapper , ilevel )
479
486
480
487
# a passed Grouper like, directly get the grouper in the same way
481
488
# as single grouper groupby, use the group_info to get codes
@@ -505,8 +512,8 @@ def __init__(
505
512
# a passed Categorical
506
513
self ._passed_categorical = True
507
514
508
- self .grouping_vector , self .all_grouper = recode_for_groupby (
509
- self .grouping_vector , self . sort , observed
515
+ self .grouping_vector , self ._all_grouper = recode_for_groupby (
516
+ self .grouping_vector , sort , observed
510
517
)
511
518
512
519
elif not isinstance (
@@ -517,11 +524,11 @@ def __init__(
517
524
t = self .name or str (type (self .grouping_vector ))
518
525
raise ValueError (f"Grouper for '{ t } ' not 1-dimensional" )
519
526
520
- self .grouping_vector = self . index .map (self .grouping_vector )
527
+ self .grouping_vector = index .map (self .grouping_vector )
521
528
522
529
if not (
523
530
hasattr (self .grouping_vector , "__len__" )
524
- and len (self .grouping_vector ) == len (self . index )
531
+ and len (self .grouping_vector ) == len (index )
525
532
):
526
533
grper = pprint_thing (self .grouping_vector )
527
534
errmsg = (
@@ -546,7 +553,7 @@ def __iter__(self):
546
553
def name (self ) -> Hashable :
547
554
ilevel = self ._ilevel
548
555
if ilevel is not None :
549
- return self .index .names [ilevel ]
556
+ return self ._index .names [ilevel ]
550
557
551
558
if isinstance (self ._orig_grouper , (Index , Series )):
552
559
return self ._orig_grouper .name
@@ -569,7 +576,7 @@ def _ilevel(self) -> int | None:
569
576
if level is None :
570
577
return None
571
578
if not isinstance (level , int ):
572
- index = self .index
579
+ index = self ._index
573
580
if level not in index .names :
574
581
raise AssertionError (f"Level { level } not in index" )
575
582
return index .names .index (level )
@@ -607,10 +614,10 @@ def group_arraylike(self) -> ArrayLike:
607
614
@cache_readonly
608
615
def result_index (self ) -> Index :
609
616
# TODO: what's the difference between result_index vs group_index?
610
- if self .all_grouper is not None :
617
+ if self ._all_grouper is not None :
611
618
group_idx = self .group_index
612
619
assert isinstance (group_idx , CategoricalIndex )
613
- return recode_from_groupby (self .all_grouper , self .sort , group_idx )
620
+ return recode_from_groupby (self ._all_grouper , self ._sort , group_idx )
614
621
return self .group_index
615
622
616
623
@cache_readonly
@@ -629,10 +636,10 @@ def _codes_and_uniques(self) -> tuple[np.ndarray, ArrayLike]:
629
636
cat = self .grouping_vector
630
637
categories = cat .categories
631
638
632
- if self .observed :
639
+ if self ._observed :
633
640
ucodes = algorithms .unique1d (cat .codes )
634
641
ucodes = ucodes [ucodes != - 1 ]
635
- if self .sort or cat .ordered :
642
+ if self ._sort or cat .ordered :
636
643
ucodes = np .sort (ucodes )
637
644
else :
638
645
ucodes = np .arange (len (categories ))
@@ -648,18 +655,18 @@ def _codes_and_uniques(self) -> tuple[np.ndarray, ArrayLike]:
648
655
uniques = self .grouping_vector .result_arraylike
649
656
else :
650
657
# GH35667, replace dropna=False with na_sentinel=None
651
- if not self .dropna :
658
+ if not self ._dropna :
652
659
na_sentinel = None
653
660
else :
654
661
na_sentinel = - 1
655
662
codes , uniques = algorithms .factorize (
656
- self .grouping_vector , sort = self .sort , na_sentinel = na_sentinel
663
+ self .grouping_vector , sort = self ._sort , na_sentinel = na_sentinel
657
664
)
658
665
return codes , uniques
659
666
660
667
@cache_readonly
661
668
def groups (self ) -> dict [Hashable , np .ndarray ]:
662
- return self .index .groupby (Categorical .from_codes (self .codes , self .group_index ))
669
+ return self ._index .groupby (Categorical .from_codes (self .codes , self .group_index ))
663
670
664
671
665
672
def get_grouper (
0 commit comments