Create and return a BaseGrouper, which is an internal mapping of how to create the grouper indexers. This may be composed of multiple Grouping objects, indicating multiple groupers Groupers are ultimately index mappings. They can originate as: index mappings, keys to column
(
obj: NDFrameT,
key=None,
level=None,
sort: bool = True,
observed: bool = False,
validate: bool = True,
dropna: bool = True,
)
| 719 | |
| 720 | |
| 721 | def get_grouper( |
| 722 | obj: NDFrameT, |
| 723 | key=None, |
| 724 | level=None, |
| 725 | sort: bool = True, |
| 726 | observed: bool = False, |
| 727 | validate: bool = True, |
| 728 | dropna: bool = True, |
| 729 | ) -> tuple[ops.BaseGrouper, frozenset[Hashable], NDFrameT]: |
| 730 | """ |
| 731 | Create and return a BaseGrouper, which is an internal |
| 732 | mapping of how to create the grouper indexers. |
| 733 | This may be composed of multiple Grouping objects, indicating |
| 734 | multiple groupers |
| 735 | |
| 736 | Groupers are ultimately index mappings. They can originate as: |
| 737 | index mappings, keys to columns, functions, or Groupers |
| 738 | |
| 739 | Groupers enable local references to level,sort, while |
| 740 | the passed in level, and sort are 'global'. |
| 741 | |
| 742 | This routine tries to figure out what the passing in references |
| 743 | are and then creates a Grouping for each one, combined into |
| 744 | a BaseGrouper. |
| 745 | |
| 746 | If observed & we have a categorical grouper, only show the observed |
| 747 | values. |
| 748 | |
| 749 | If validate, then check for key/level overlaps. |
| 750 | |
| 751 | """ |
| 752 | group_axis = obj.index |
| 753 | |
| 754 | # validate that the passed single level is compatible with the passed |
| 755 | # index of the object |
| 756 | if level is not None: |
| 757 | # TODO: These if-block and else-block are almost same. |
| 758 | # MultiIndex instance check is removable, but it seems that there are |
| 759 | # some processes only for non-MultiIndex in else-block, |
| 760 | # eg. `obj.index.name != level`. We have to consider carefully whether |
| 761 | # these are applicable for MultiIndex. Even if these are applicable, |
| 762 | # we need to check if it makes no side effect to subsequent processes |
| 763 | # on the outside of this condition. |
| 764 | # (GH 17621) |
| 765 | if isinstance(group_axis, MultiIndex): |
| 766 | if is_list_like(level) and len(level) == 1: |
| 767 | level = level[0] |
| 768 | |
| 769 | if key is None and is_scalar(level): |
| 770 | # Get the level values from group_axis |
| 771 | key = group_axis.get_level_values(level) |
| 772 | level = None |
| 773 | |
| 774 | else: |
| 775 | # allow level to be a length-one list-like object |
| 776 | # (e.g., level=[0]) |
| 777 | # GH 13901 |
| 778 | if is_list_like(level): |
no test coverage detected