Skip to content

BUG: Validate the ordered parameter for Categorical #14059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.19.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@ Bug Fixes
- Bug in ``DataFrame`` assignment with an object-dtyped ``Index`` where the resultant column is mutable to the original object. (:issue:`13522`)
- Bug in matplotlib ``AutoDataFormatter``; this restores the second scaled formatting and re-adds micro-second scaled formatting (:issue:`13131`)
- Bug in selection from a ``HDFStore`` with a fixed format and ``start`` and/or ``stop`` specified will now return the selected range (:issue:`8287`)
- Bug in ``Categorical.from_codes()`` where an unhelpful error was raised when an invalid ``ordered`` parameter was passed in (:issue:`14058`)
- Bug in ``Series`` construction from a tuple of integers on windows not returning default dtype (int64) (:issue:`13646`)

- Bug in ``.groupby(..).resample(..)`` when the same object is called multiple times (:issue:`13174`)
Expand Down
24 changes: 22 additions & 2 deletions pandas/core/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ class Categorical(PandasObject):
def __init__(self, values, categories=None, ordered=False,
name=None, fastpath=False):

self._validate_ordered(ordered)

if fastpath:
# fast path
self._codes = _coerce_indexer_dtype(values, categories)
Expand Down Expand Up @@ -502,6 +504,25 @@ def _get_labels(self):

_categories = None

@classmethod
def _validate_ordered(cls, ordered):
"""
Validates that we have a valid ordered parameter. If
it is not a boolean, a TypeError will be raised.

Parameters
----------
ordered : object
The parameter to be verified.

Raises
------
TypeError
If 'ordered' is not a boolean.
"""
if not is_bool(ordered):
raise TypeError("'ordered' must either be 'True' or 'False'")

@classmethod
def _validate_categories(cls, categories, fastpath=False):
"""
Expand Down Expand Up @@ -588,8 +609,7 @@ def set_ordered(self, value, inplace=False):
Whether or not to set the ordered attribute inplace or return a copy
of this categorical with ordered set to the value
"""
if not is_bool(value):
raise TypeError("ordered must be a boolean value")
self._validate_ordered(value)
cat = self if inplace else self.copy()
cat._ordered = value
if not inplace:
Expand Down
1 change: 1 addition & 0 deletions pandas/indexes/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ def _create_categorical(self, data, categories=None, ordered=None):
Categorical
"""
if not isinstance(data, ABCCategorical):
ordered = False if ordered is None else ordered
from pandas.core.categorical import Categorical
data = Categorical(data, categories=categories, ordered=ordered)
else:
Expand Down
18 changes: 18 additions & 0 deletions pandas/tests/test_categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,24 @@ def f():
codes = np.random.choice([0, 1], 5, p=[0.9, 0.1])
pd.Categorical.from_codes(codes, categories=["train", "test"])

def test_validate_ordered(self):
# see gh-14058
exp_msg = "'ordered' must either be 'True' or 'False'"
exp_err = TypeError

# This should be a boolean.
ordered = np.array([0, 1, 2])

with tm.assertRaisesRegexp(exp_err, exp_msg):
Categorical([1, 2, 3], ordered=ordered)

with tm.assertRaisesRegexp(exp_err, exp_msg):
Categorical.from_array([1, 2, 3], ordered=ordered)

with tm.assertRaisesRegexp(exp_err, exp_msg):
Categorical.from_codes([0, 0, 1], categories=['a', 'b', 'c'],
ordered=ordered)

def test_comparisons(self):

result = self.factor[self.factor == 'a']
Expand Down