diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 4fa6b73932aa4..27e0a198b62a2 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -1376,7 +1376,7 @@ def value_counts(self, dropna=True): count = np.bincount(np.where(mask, code, ncat)) ix = np.append(ix, -1) - ix = self._constructor(ix, dtype=self.dtype, fastpath=True) + ix = self._from_backing_data(ix) return Series(count, index=CategoricalIndex(ix), dtype="int64") @@ -1546,9 +1546,8 @@ def sort_values( if inplace: self._codes = self._codes[sorted_idx] else: - return self._constructor( - values=self._codes[sorted_idx], dtype=self.dtype, fastpath=True - ) + codes = self._codes[sorted_idx] + return self._from_backing_data(codes) def _values_for_rank(self): """ @@ -1583,7 +1582,7 @@ def _values_for_rank(self): def view(self, dtype=None): if dtype is not None: raise NotImplementedError(dtype) - return self._constructor(values=self._codes, dtype=self.dtype, fastpath=True) + return self._from_backing_data(self._ndarray) def to_dense(self): """ @@ -1691,7 +1690,7 @@ def fillna(self, value=None, method=None, limit=None): f"or Series, but you passed a {type(value).__name__}" ) - return self._constructor(codes, dtype=self.dtype, fastpath=True) + return self._from_backing_data(codes) # ------------------------------------------------------------------ # NDArrayBackedExtensionArray compat @@ -2098,7 +2097,7 @@ def mode(self, dropna=True): good = self._codes != -1 codes = self._codes[good] codes = sorted(htable.mode_int64(ensure_int64(codes), dropna)) - return self._constructor(values=codes, dtype=self.dtype, fastpath=True) + return self._from_backing_data(codes) # ------------------------------------------------------------------ # ExtensionArray Interface diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index 19a0910a7a282..85ef3e58576e3 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -211,29 +211,6 @@ def __new__( return cls._simple_new(data, name=name) - def _create_from_codes(self, codes, dtype=None, name=None): - """ - *this is an internal non-public method* - - create the correct categorical from codes - - Parameters - ---------- - codes : new codes - dtype: CategoricalDtype, defaults to existing - name : optional name attribute, defaults to existing - - Returns - ------- - CategoricalIndex - """ - if dtype is None: - dtype = self.dtype - if name is None: - name = self.name - cat = Categorical.from_codes(codes, dtype=dtype) - return CategoricalIndex(cat, name=name) - @classmethod def _simple_new(cls, values: Categorical, name: Label = None): assert isinstance(values, Categorical), type(values) @@ -495,7 +472,8 @@ def reindex(self, target, method=None, level=None, limit=None, tolerance=None): codes = new_target.codes.copy() codes[indexer == -1] = cats[missing] - new_target = self._create_from_codes(codes) + cat = self._data._from_backing_data(codes) + new_target = type(self)._simple_new(cat, name=self.name) # we always want to return an Index type here # to be consistent with .reindex for other index types (e.g. they don't @@ -695,7 +673,9 @@ def delete(self, loc): ------- new_index : Index """ - return self._create_from_codes(np.delete(self.codes, loc)) + codes = np.delete(self.codes, loc) + cat = self._data._from_backing_data(codes) + return type(self)._simple_new(cat, name=self.name) def insert(self, loc: int, item): """ @@ -720,15 +700,14 @@ def insert(self, loc: int, item): codes = self.codes codes = np.concatenate((codes[:loc], [code], codes[loc:])) - return self._create_from_codes(codes) + cat = self._data._from_backing_data(codes) + return type(self)._simple_new(cat, name=self.name) def _concat(self, to_concat, name): # if calling index is category, don't check dtype of others codes = np.concatenate([self._is_dtype_compat(c).codes for c in to_concat]) - result = self._create_from_codes(codes, name=name) - # if name is None, _create_from_codes sets self.name - result.name = name - return result + cat = self._data._from_backing_data(codes) + return type(self)._simple_new(cat, name=name) def _delegate_method(self, name: str, *args, **kwargs): """ method delegation to the ._values """