|
25 | 25 | is_timedelta64_dtype,
|
26 | 26 | is_categorical,
|
27 | 27 | is_categorical_dtype,
|
| 28 | + is_integer_dtype, |
28 | 29 | is_list_like, is_sequence,
|
29 | 30 | is_scalar,
|
30 | 31 | is_dict_like)
|
@@ -244,44 +245,8 @@ class Categorical(PandasObject):
|
244 | 245 | def __init__(self, values, categories=None, ordered=None, dtype=None,
|
245 | 246 | fastpath=False):
|
246 | 247 |
|
247 |
| - # Ways of specifying the dtype (prioritized ordered) |
248 |
| - # 1. dtype is a CategoricalDtype |
249 |
| - # a.) with known categories, use dtype.categories |
250 |
| - # b.) else with Categorical values, use values.dtype |
251 |
| - # c.) else, infer from values |
252 |
| - # d.) specifying dtype=CategoricalDtype and categories is an error |
253 |
| - # 2. dtype is a string 'category' |
254 |
| - # a.) use categories, ordered |
255 |
| - # b.) use values.dtype |
256 |
| - # c.) infer from values |
257 |
| - # 3. dtype is None |
258 |
| - # a.) use categories, ordered |
259 |
| - # b.) use values.dtype |
260 |
| - # c.) infer from values |
261 |
| - |
262 |
| - if dtype is not None: |
263 |
| - # The dtype argument takes precedence over values.dtype (if any) |
264 |
| - if isinstance(dtype, compat.string_types): |
265 |
| - if dtype == 'category': |
266 |
| - dtype = CategoricalDtype(categories, ordered) |
267 |
| - else: |
268 |
| - msg = "Unknown `dtype` {dtype}" |
269 |
| - raise ValueError(msg.format(dtype=dtype)) |
270 |
| - elif categories is not None or ordered is not None: |
271 |
| - raise ValueError("Cannot specify both `dtype` and `categories`" |
272 |
| - " or `ordered`.") |
273 |
| - |
274 |
| - categories = dtype.categories |
275 |
| - ordered = dtype.ordered |
276 |
| - |
277 |
| - elif is_categorical(values): |
278 |
| - # If no "dtype" was passed, use the one from "values", but honor |
279 |
| - # the "ordered" and "categories" arguments |
280 |
| - dtype = values.dtype._from_categorical_dtype(values.dtype, |
281 |
| - categories, ordered) |
282 |
| - else: |
283 |
| - # If dtype=None and values is not categorical, create a new dtype |
284 |
| - dtype = CategoricalDtype(categories, ordered) |
| 248 | + categories, ordered, dtype = validate_dtype(values, categories, |
| 249 | + ordered, dtype) |
285 | 250 |
|
286 | 251 | # At this point, dtype is always a CategoricalDtype
|
287 | 252 | # if dtype.categories is None, we are inferring
|
@@ -347,6 +312,13 @@ def __init__(self, values, categories=None, ordered=None, dtype=None,
|
347 | 312 | dtype.categories)
|
348 | 313 |
|
349 | 314 | else:
|
| 315 | + # there were two ways if categories are present |
| 316 | + # - the old one, where each value is a int pointer to the levels |
| 317 | + # array -> not anymore possible, but code outside of pandas could |
| 318 | + # call us like that, so make some checks |
| 319 | + # - the new one, where each value is also in the categories array |
| 320 | + # (or np.nan) |
| 321 | + |
350 | 322 | codes = _get_codes_for_values(values, dtype.categories)
|
351 | 323 |
|
352 | 324 | if null_mask.any():
|
@@ -875,6 +847,11 @@ def set_categories(self, new_categories, ordered=None, rename=False,
|
875 | 847 | def rename_categories(self, new_categories, inplace=False):
|
876 | 848 | """ Renames categories.
|
877 | 849 |
|
| 850 | + The new categories can be either a list-like dict-like object. |
| 851 | + If it is list-like, all items must be unique and the number of items |
| 852 | + in the new categories must be the same as the number of items in the |
| 853 | + old categories. |
| 854 | +
|
878 | 855 | Raises
|
879 | 856 | ------
|
880 | 857 | ValueError
|
@@ -915,33 +892,10 @@ def rename_categories(self, new_categories, inplace=False):
|
915 | 892 | remove_categories
|
916 | 893 | remove_unused_categories
|
917 | 894 | set_categories
|
918 |
| -
|
919 |
| - Examples |
920 |
| - -------- |
921 |
| - >>> c = Categorical(['a', 'a', 'b']) |
922 |
| - >>> c.rename_categories([0, 1]) |
923 |
| - [0, 0, 1] |
924 |
| - Categories (2, int64): [0, 1] |
925 |
| -
|
926 |
| - For dict-like ``new_categories``, extra keys are ignored and |
927 |
| - categories not in the dictionary are passed through |
928 |
| -
|
929 |
| - >>> c.rename_categories({'a': 'A', 'c': 'C'}) |
930 |
| - [A, A, b] |
931 |
| - Categories (2, object): [A, b] |
932 | 895 | """
|
933 | 896 | inplace = validate_bool_kwarg(inplace, 'inplace')
|
934 | 897 | cat = self if inplace else self.copy()
|
935 | 898 |
|
936 |
| - if isinstance(new_categories, ABCSeries): |
937 |
| - msg = ("Treating Series 'new_categories' as a list-like and using " |
938 |
| - "the values. In a future version, 'rename_categories' will " |
939 |
| - "treat Series like a dictionary.\n" |
940 |
| - "For dict-like, use 'new_categories.to_dict()'\n" |
941 |
| - "For list-like, use 'new_categories.values'.") |
942 |
| - warn(msg, FutureWarning, stacklevel=2) |
943 |
| - new_categories = list(new_categories) |
944 |
| - |
945 | 899 | if is_dict_like(new_categories):
|
946 | 900 | cat.categories = [new_categories.get(item, item)
|
947 | 901 | for item in cat.categories]
|
|
0 commit comments