Skip to content

Commit a14d64d

Browse files
jbrockmendelKevin D Smith
authored and
Kevin D Smith
committed
REF: collect methods by topic (pandas-dev#36173)
1 parent 8272c16 commit a14d64d

File tree

9 files changed

+212
-153
lines changed

9 files changed

+212
-153
lines changed

pandas/core/arrays/categorical.py

+82-66
Original file line numberDiff line numberDiff line change
@@ -393,56 +393,6 @@ def __init__(
393393
self._dtype = self._dtype.update_dtype(dtype)
394394
self._codes = coerce_indexer_dtype(codes, dtype.categories)
395395

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-
446396
@property
447397
def dtype(self) -> CategoricalDtype:
448398
"""
@@ -458,10 +408,6 @@ def _constructor(self) -> Type["Categorical"]:
458408
def _from_sequence(cls, scalars, dtype=None, copy=False):
459409
return Categorical(scalars, dtype=dtype)
460410

461-
def _formatter(self, boxed=False):
462-
# Defer to CategoricalFormatter's formatter.
463-
return None
464-
465411
def astype(self, dtype: Dtype, copy: bool = True) -> ArrayLike:
466412
"""
467413
Coerce this type to another dtype
@@ -640,6 +586,59 @@ def from_codes(cls, codes, categories=None, ordered=None, dtype=None):
640586

641587
return cls(codes, dtype=dtype, fastpath=True)
642588

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+
643642
@property
644643
def codes(self) -> np.ndarray:
645644
"""
@@ -1104,6 +1103,8 @@ def remove_unused_categories(self, inplace=False):
11041103
if not inplace:
11051104
return cat
11061105

1106+
# ------------------------------------------------------------------
1107+
11071108
def map(self, mapper):
11081109
"""
11091110
Map categories using input correspondence (dict, Series, or function).
@@ -1192,6 +1193,9 @@ def map(self, mapper):
11921193
__le__ = _cat_compare_op(operator.le)
11931194
__ge__ = _cat_compare_op(operator.ge)
11941195

1196+
# -------------------------------------------------------------
1197+
# Validators; ideally these can be de-duplicated
1198+
11951199
def _validate_insert_value(self, value) -> int:
11961200
code = self.categories.get_indexer([value])
11971201
if (code == -1) and not (is_scalar(value) and isna(value)):
@@ -1241,6 +1245,8 @@ def _validate_fill_value(self, fill_value):
12411245
)
12421246
return fill_value
12431247

1248+
# -------------------------------------------------------------
1249+
12441250
def __array__(self, dtype=None) -> np.ndarray:
12451251
"""
12461252
The numpy array interface.
@@ -1758,6 +1764,10 @@ def __contains__(self, key) -> bool:
17581764
# ------------------------------------------------------------------
17591765
# Rendering Methods
17601766

1767+
def _formatter(self, boxed=False):
1768+
# Defer to CategoricalFormatter's formatter.
1769+
return None
1770+
17611771
def _tidy_repr(self, max_vals=10, footer=True) -> str:
17621772
"""
17631773
a short repr displaying only max_vals and an optional (but default
@@ -1987,7 +1997,9 @@ def _reverse_indexer(self) -> Dict[Hashable, np.ndarray]:
19871997
result = dict(zip(categories, _result))
19881998
return result
19891999

1990-
# reduction ops #
2000+
# ------------------------------------------------------------------
2001+
# Reductions
2002+
19912003
def _reduce(self, name: str, skipna: bool = True, **kwargs):
19922004
func = getattr(self, name, None)
19932005
if func is None:
@@ -2090,6 +2102,9 @@ def mode(self, dropna=True):
20902102
codes = sorted(htable.mode_int64(ensure_int64(codes), dropna))
20912103
return self._constructor(values=codes, dtype=self.dtype, fastpath=True)
20922104

2105+
# ------------------------------------------------------------------
2106+
# ExtensionArray Interface
2107+
20932108
def unique(self):
20942109
"""
20952110
Return the ``Categorical`` which ``categories`` and ``codes`` are
@@ -2179,6 +2194,18 @@ def equals(self, other: object) -> bool:
21792194
return np.array_equal(self._codes, other_codes)
21802195
return False
21812196

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+
21822209
def is_dtype_equal(self, other):
21832210
"""
21842211
Returns True if categoricals are the same dtype
@@ -2217,17 +2244,6 @@ def describe(self):
22172244

22182245
return result
22192246

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-
22312247
def isin(self, values) -> np.ndarray:
22322248
"""
22332249
Check whether `values` are contained in Categorical.

pandas/core/indexes/category.py

+17-12
Original file line numberDiff line numberDiff line change
@@ -433,11 +433,6 @@ def _to_safe_for_reshape(self):
433433
""" convert to object if we are a categorical """
434434
return self.astype("object")
435435

436-
def _maybe_cast_indexer(self, key):
437-
code = self.categories.get_loc(key)
438-
code = self.codes.dtype.type(code)
439-
return code
440-
441436
@doc(Index.where)
442437
def where(self, cond, other=None):
443438
# TODO: Investigate an alternative implementation with
@@ -537,6 +532,14 @@ def _reindex_non_unique(self, target):
537532

538533
return new_target, indexer, new_indexer
539534

535+
# --------------------------------------------------------------------
536+
# Indexing Methods
537+
538+
def _maybe_cast_indexer(self, key):
539+
code = self.categories.get_loc(key)
540+
code = self.codes.dtype.type(code)
541+
return code
542+
540543
@Appender(_index_shared_docs["get_indexer"] % _index_doc_kwargs)
541544
def get_indexer(self, target, method=None, limit=None, tolerance=None):
542545
method = missing.clean_reindex_fill_method(method)
@@ -619,6 +622,15 @@ def _convert_arr_indexer(self, keyarr):
619622
def _convert_index_indexer(self, keyarr):
620623
return self._shallow_copy(keyarr)
621624

625+
@doc(Index._maybe_cast_slice_bound)
626+
def _maybe_cast_slice_bound(self, label, side, kind):
627+
if kind == "loc":
628+
return label
629+
630+
return super()._maybe_cast_slice_bound(label, side, kind)
631+
632+
# --------------------------------------------------------------------
633+
622634
def take_nd(self, *args, **kwargs):
623635
"""Alias for `take`"""
624636
warnings.warn(
@@ -628,13 +640,6 @@ def take_nd(self, *args, **kwargs):
628640
)
629641
return self.take(*args, **kwargs)
630642

631-
@doc(Index._maybe_cast_slice_bound)
632-
def _maybe_cast_slice_bound(self, label, side, kind):
633-
if kind == "loc":
634-
return label
635-
636-
return super()._maybe_cast_slice_bound(label, side, kind)
637-
638643
def map(self, mapper):
639644
"""
640645
Map values using input correspondence (a dict, Series, or function).

pandas/core/indexes/datetimes.py

+3
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,9 @@ def snap(self, freq="S"):
509509
dta = DatetimeArray(snapped, dtype=self.dtype)
510510
return DatetimeIndex._simple_new(dta, name=self.name)
511511

512+
# --------------------------------------------------------------------
513+
# Indexing Methods
514+
512515
def _parsed_string_to_bounds(self, reso: Resolution, parsed: datetime):
513516
"""
514517
Calculate datetime bounds for parsed time string and its resolution.

0 commit comments

Comments
 (0)