@@ -393,56 +393,6 @@ def __init__(
393
393
self ._dtype = self ._dtype .update_dtype (dtype )
394
394
self ._codes = coerce_indexer_dtype (codes , dtype .categories )
395
395
396
- @property
397
- def categories (self ):
398
- """
399
- The categories of this categorical.
400
-
401
- Setting assigns new values to each category (effectively a rename of
402
- each individual category).
403
-
404
- The assigned value has to be a list-like object. All items must be
405
- unique and the number of items in the new categories must be the same
406
- as the number of items in the old categories.
407
-
408
- Assigning to `categories` is a inplace operation!
409
-
410
- Raises
411
- ------
412
- ValueError
413
- If the new categories do not validate as categories or if the
414
- number of new categories is unequal the number of old categories
415
-
416
- See Also
417
- --------
418
- rename_categories : Rename categories.
419
- reorder_categories : Reorder categories.
420
- add_categories : Add new categories.
421
- remove_categories : Remove the specified categories.
422
- remove_unused_categories : Remove categories which are not used.
423
- set_categories : Set the categories to the specified ones.
424
- """
425
- return self .dtype .categories
426
-
427
- @categories .setter
428
- def categories (self , categories ):
429
- new_dtype = CategoricalDtype (categories , ordered = self .ordered )
430
- if self .dtype .categories is not None and len (self .dtype .categories ) != len (
431
- new_dtype .categories
432
- ):
433
- raise ValueError (
434
- "new categories need to have the same number of "
435
- "items as the old categories!"
436
- )
437
- self ._dtype = new_dtype
438
-
439
- @property
440
- def ordered (self ) -> Ordered :
441
- """
442
- Whether the categories have an ordered relationship.
443
- """
444
- return self .dtype .ordered
445
-
446
396
@property
447
397
def dtype (self ) -> CategoricalDtype :
448
398
"""
@@ -458,10 +408,6 @@ def _constructor(self) -> Type["Categorical"]:
458
408
def _from_sequence (cls , scalars , dtype = None , copy = False ):
459
409
return Categorical (scalars , dtype = dtype )
460
410
461
- def _formatter (self , boxed = False ):
462
- # Defer to CategoricalFormatter's formatter.
463
- return None
464
-
465
411
def astype (self , dtype : Dtype , copy : bool = True ) -> ArrayLike :
466
412
"""
467
413
Coerce this type to another dtype
@@ -640,6 +586,59 @@ def from_codes(cls, codes, categories=None, ordered=None, dtype=None):
640
586
641
587
return cls (codes , dtype = dtype , fastpath = True )
642
588
589
+ # ------------------------------------------------------------------
590
+ # Categories/Codes/Ordered
591
+
592
+ @property
593
+ def categories (self ):
594
+ """
595
+ The categories of this categorical.
596
+
597
+ Setting assigns new values to each category (effectively a rename of
598
+ each individual category).
599
+
600
+ The assigned value has to be a list-like object. All items must be
601
+ unique and the number of items in the new categories must be the same
602
+ as the number of items in the old categories.
603
+
604
+ Assigning to `categories` is a inplace operation!
605
+
606
+ Raises
607
+ ------
608
+ ValueError
609
+ If the new categories do not validate as categories or if the
610
+ number of new categories is unequal the number of old categories
611
+
612
+ See Also
613
+ --------
614
+ rename_categories : Rename categories.
615
+ reorder_categories : Reorder categories.
616
+ add_categories : Add new categories.
617
+ remove_categories : Remove the specified categories.
618
+ remove_unused_categories : Remove categories which are not used.
619
+ set_categories : Set the categories to the specified ones.
620
+ """
621
+ return self .dtype .categories
622
+
623
+ @categories .setter
624
+ def categories (self , categories ):
625
+ new_dtype = CategoricalDtype (categories , ordered = self .ordered )
626
+ if self .dtype .categories is not None and len (self .dtype .categories ) != len (
627
+ new_dtype .categories
628
+ ):
629
+ raise ValueError (
630
+ "new categories need to have the same number of "
631
+ "items as the old categories!"
632
+ )
633
+ self ._dtype = new_dtype
634
+
635
+ @property
636
+ def ordered (self ) -> Ordered :
637
+ """
638
+ Whether the categories have an ordered relationship.
639
+ """
640
+ return self .dtype .ordered
641
+
643
642
@property
644
643
def codes (self ) -> np .ndarray :
645
644
"""
@@ -1104,6 +1103,8 @@ def remove_unused_categories(self, inplace=False):
1104
1103
if not inplace :
1105
1104
return cat
1106
1105
1106
+ # ------------------------------------------------------------------
1107
+
1107
1108
def map (self , mapper ):
1108
1109
"""
1109
1110
Map categories using input correspondence (dict, Series, or function).
@@ -1192,6 +1193,9 @@ def map(self, mapper):
1192
1193
__le__ = _cat_compare_op (operator .le )
1193
1194
__ge__ = _cat_compare_op (operator .ge )
1194
1195
1196
+ # -------------------------------------------------------------
1197
+ # Validators; ideally these can be de-duplicated
1198
+
1195
1199
def _validate_insert_value (self , value ) -> int :
1196
1200
code = self .categories .get_indexer ([value ])
1197
1201
if (code == - 1 ) and not (is_scalar (value ) and isna (value )):
@@ -1241,6 +1245,8 @@ def _validate_fill_value(self, fill_value):
1241
1245
)
1242
1246
return fill_value
1243
1247
1248
+ # -------------------------------------------------------------
1249
+
1244
1250
def __array__ (self , dtype = None ) -> np .ndarray :
1245
1251
"""
1246
1252
The numpy array interface.
@@ -1758,6 +1764,10 @@ def __contains__(self, key) -> bool:
1758
1764
# ------------------------------------------------------------------
1759
1765
# Rendering Methods
1760
1766
1767
+ def _formatter (self , boxed = False ):
1768
+ # Defer to CategoricalFormatter's formatter.
1769
+ return None
1770
+
1761
1771
def _tidy_repr (self , max_vals = 10 , footer = True ) -> str :
1762
1772
"""
1763
1773
a short repr displaying only max_vals and an optional (but default
@@ -1987,7 +1997,9 @@ def _reverse_indexer(self) -> Dict[Hashable, np.ndarray]:
1987
1997
result = dict (zip (categories , _result ))
1988
1998
return result
1989
1999
1990
- # reduction ops #
2000
+ # ------------------------------------------------------------------
2001
+ # Reductions
2002
+
1991
2003
def _reduce (self , name : str , skipna : bool = True , ** kwargs ):
1992
2004
func = getattr (self , name , None )
1993
2005
if func is None :
@@ -2090,6 +2102,9 @@ def mode(self, dropna=True):
2090
2102
codes = sorted (htable .mode_int64 (ensure_int64 (codes ), dropna ))
2091
2103
return self ._constructor (values = codes , dtype = self .dtype , fastpath = True )
2092
2104
2105
+ # ------------------------------------------------------------------
2106
+ # ExtensionArray Interface
2107
+
2093
2108
def unique (self ):
2094
2109
"""
2095
2110
Return the ``Categorical`` which ``categories`` and ``codes`` are
@@ -2179,6 +2194,18 @@ def equals(self, other: object) -> bool:
2179
2194
return np .array_equal (self ._codes , other_codes )
2180
2195
return False
2181
2196
2197
+ @property
2198
+ def _can_hold_na (self ):
2199
+ return True
2200
+
2201
+ @classmethod
2202
+ def _concat_same_type (self , to_concat ):
2203
+ from pandas .core .dtypes .concat import union_categoricals
2204
+
2205
+ return union_categoricals (to_concat )
2206
+
2207
+ # ------------------------------------------------------------------
2208
+
2182
2209
def is_dtype_equal (self , other ):
2183
2210
"""
2184
2211
Returns True if categoricals are the same dtype
@@ -2217,17 +2244,6 @@ def describe(self):
2217
2244
2218
2245
return result
2219
2246
2220
- # Implement the ExtensionArray interface
2221
- @property
2222
- def _can_hold_na (self ):
2223
- return True
2224
-
2225
- @classmethod
2226
- def _concat_same_type (self , to_concat ):
2227
- from pandas .core .dtypes .concat import union_categoricals
2228
-
2229
- return union_categoricals (to_concat )
2230
-
2231
2247
def isin (self , values ) -> np .ndarray :
2232
2248
"""
2233
2249
Check whether `values` are contained in Categorical.
0 commit comments