diff --git a/pandas/core/groupby/grouper.py b/pandas/core/groupby/grouper.py index 5f680de77649f..f617c142cb48d 100644 --- a/pandas/core/groupby/grouper.py +++ b/pandas/core/groupby/grouper.py @@ -441,6 +441,7 @@ def __init__( in_axis: bool = False, dropna: bool = True, uniques: ArrayLike | None = None, + key_dtype_str: bool = False, ) -> None: self.level = level self._orig_grouper = grouper @@ -453,6 +454,7 @@ def __init__( self.in_axis = in_axis self._dropna = dropna self._uniques = uniques + self.key_dtype_str = key_dtype_str # we have a single grouper which may be a myriad of things, # some of which are dependent on the passing in level @@ -667,6 +669,8 @@ def groups(self) -> dict[Hashable, Index]: codes, uniques = self._codes_and_uniques uniques = Index._with_infer(uniques, name=self.name) cats = Categorical.from_codes(codes, uniques, validate=False) + if not self.key_dtype_str: + cats = [(i,) for i in cats] return self._index.groupby(cats) @property @@ -781,7 +785,9 @@ def get_grouper( elif isinstance(key, ops.BaseGrouper): return key, frozenset(), obj + key_dtype_str = False if not isinstance(key, list): + key_dtype_str = True keys = [key] match_axis_length = False else: @@ -892,11 +898,11 @@ def is_in_obj(gpr) -> bool: observed=observed, in_axis=in_axis, dropna=dropna, + key_dtype_str=key_dtype_str, ) if not isinstance(gpr, Grouping) else gpr ) - groupings.append(ping) if len(groupings) == 0 and len(obj): diff --git a/pandas/tests/groupby/test_groupby.py b/pandas/tests/groupby/test_groupby.py index 13fb9cfc4c0e4..d950f99054df5 100644 --- a/pandas/tests/groupby/test_groupby.py +++ b/pandas/tests/groupby/test_groupby.py @@ -2996,3 +2996,10 @@ def test_groupby_multi_index_codes(): index = df_grouped.index tm.assert_index_equal(index, MultiIndex.from_frame(index.to_frame())) + + +def test_groupby_keys_1length_list(): + # GH#58945 + df = DataFrame({"x": [10, 20, 30], "y": ["a", "b", "c"]}) + result = df.groupby(["x"]).groups + assert all(isinstance(key, tuple) for key in result.keys())