Skip to content

Commit d7c028d

Browse files
gfyoungjreback
authored andcommitted
CLN: Removed levels attribute from Categorical
Deprecated back in `0.15.0` and therefore long overdue. Closes pandas-dev#8376. Author: gfyoung <[email protected]> Closes pandas-dev#13612 from gfyoung/categorical-levels-remove and squashes the following commits: f1254df [gfyoung] MAINT: Relocated backwards compat categorical pickle tests f3321cb [gfyoung] CLN: Removed levels attribute from Categorical
1 parent 1bee56e commit d7c028d

File tree

7 files changed

+43
-80
lines changed

7 files changed

+43
-80
lines changed

doc/source/whatsnew/v0.19.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ Removal of prior version deprecations/changes
506506

507507
- ``DataFrame.to_csv()`` has dropped the ``engine`` parameter, as was deprecated in 0.17.1 (:issue:`11274`, :issue:`13419`)
508508
- ``DataFrame.to_dict()`` has dropped the ``outtype`` parameter in favor of ``orient`` (:issue:`13627`, :issue:`8486`)
509+
- ``pd.Categorical`` has dropped the ``levels`` attribute in favour of ``categories`` (:issue:`8376`)
509510

510511

511512
.. _whatsnew_0190.performance:

pandas/core/categorical.py

+2-28
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ class Categorical(PandasObject):
228228
__array_priority__ = 1000
229229
_typ = 'categorical'
230230

231-
def __init__(self, values, categories=None, ordered=False, name=None,
232-
fastpath=False, levels=None):
231+
def __init__(self, values, categories=None, ordered=False,
232+
name=None, fastpath=False):
233233

234234
if fastpath:
235235
# fast path
@@ -245,17 +245,6 @@ def __init__(self, values, categories=None, ordered=False, name=None,
245245
"name=\"something\")'")
246246
warn(msg, UserWarning, stacklevel=2)
247247

248-
# TODO: Remove after deprecation period in 2017/ after 0.18
249-
if levels is not None:
250-
warn("Creating a 'Categorical' with 'levels' is deprecated, use "
251-
"'categories' instead", FutureWarning, stacklevel=2)
252-
if categories is None:
253-
categories = levels
254-
else:
255-
raise ValueError("Cannot pass in both 'categories' and "
256-
"(deprecated) 'levels', use only "
257-
"'categories'", stacklevel=2)
258-
259248
# sanitize input
260249
if is_categorical_dtype(values):
261250

@@ -580,21 +569,6 @@ def _get_categories(self):
580569
categories = property(fget=_get_categories, fset=_set_categories,
581570
doc=_categories_doc)
582571

583-
def _set_levels(self, levels):
584-
""" set new levels (deprecated, use "categories") """
585-
warn("Assigning to 'levels' is deprecated, use 'categories'",
586-
FutureWarning, stacklevel=2)
587-
self.categories = levels
588-
589-
def _get_levels(self):
590-
""" Gets the levels (deprecated, use "categories") """
591-
warn("Accessing 'levels' is deprecated, use 'categories'",
592-
FutureWarning, stacklevel=2)
593-
return self.categories
594-
595-
# TODO: Remove after deprecation period in 2017/ after 0.18
596-
levels = property(fget=_get_levels, fset=_set_levels)
597-
598572
_ordered = None
599573

600574
def _set_ordered(self, value):

pandas/io/tests/test_pickle.py

+38
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,44 @@ def python_unpickler(path):
231231
result = python_unpickler(path)
232232
self.compare_element(result, expected, typ)
233233

234+
def test_pickle_v0_14_1(self):
235+
236+
# we have the name warning
237+
# 10482
238+
with tm.assert_produces_warning(UserWarning):
239+
cat = pd.Categorical(values=['a', 'b', 'c'],
240+
categories=['a', 'b', 'c', 'd'],
241+
name='foobar', ordered=False)
242+
pickle_path = os.path.join(tm.get_data_path(),
243+
'categorical_0_14_1.pickle')
244+
# This code was executed once on v0.14.1 to generate the pickle:
245+
#
246+
# cat = Categorical(labels=np.arange(3), levels=['a', 'b', 'c', 'd'],
247+
# name='foobar')
248+
# with open(pickle_path, 'wb') as f: pickle.dump(cat, f)
249+
#
250+
tm.assert_categorical_equal(cat, pd.read_pickle(pickle_path))
251+
252+
def test_pickle_v0_15_2(self):
253+
# ordered -> _ordered
254+
# GH 9347
255+
256+
# we have the name warning
257+
# 10482
258+
with tm.assert_produces_warning(UserWarning):
259+
cat = pd.Categorical(values=['a', 'b', 'c'],
260+
categories=['a', 'b', 'c', 'd'],
261+
name='foobar', ordered=False)
262+
pickle_path = os.path.join(tm.get_data_path(),
263+
'categorical_0_15_2.pickle')
264+
# This code was executed once on v0.15.2 to generate the pickle:
265+
#
266+
# cat = Categorical(labels=np.arange(3), levels=['a', 'b', 'c', 'd'],
267+
# name='foobar')
268+
# with open(pickle_path, 'wb') as f: pickle.dump(cat, f)
269+
#
270+
tm.assert_categorical_equal(cat, pd.read_pickle(pickle_path))
271+
234272

235273
if __name__ == '__main__':
236274
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],

pandas/tests/test_categorical.py

-50
Original file line numberDiff line numberDiff line change
@@ -1559,18 +1559,6 @@ def test_deprecated_labels(self):
15591559
res = cat.labels
15601560
self.assert_numpy_array_equal(res, exp)
15611561

1562-
def test_deprecated_levels(self):
1563-
# TODO: levels is deprecated and should be removed in 0.18 or 2017,
1564-
# whatever is earlier
1565-
cat = pd.Categorical([1, 2, 3, np.nan], categories=[1, 2, 3])
1566-
exp = cat.categories
1567-
with tm.assert_produces_warning(FutureWarning):
1568-
res = cat.levels
1569-
self.assert_index_equal(res, exp)
1570-
with tm.assert_produces_warning(FutureWarning):
1571-
res = pd.Categorical([1, 2, 3, np.nan], levels=[1, 2, 3])
1572-
self.assert_index_equal(res.categories, exp)
1573-
15741562
def test_removed_names_produces_warning(self):
15751563

15761564
# 10482
@@ -4431,44 +4419,6 @@ def test_dt_accessor_api_for_categorical(self):
44314419
invalid.dt
44324420
self.assertFalse(hasattr(invalid, 'str'))
44334421

4434-
def test_pickle_v0_14_1(self):
4435-
4436-
# we have the name warning
4437-
# 10482
4438-
with tm.assert_produces_warning(UserWarning):
4439-
cat = pd.Categorical(values=['a', 'b', 'c'],
4440-
categories=['a', 'b', 'c', 'd'],
4441-
name='foobar', ordered=False)
4442-
pickle_path = os.path.join(tm.get_data_path(),
4443-
'categorical_0_14_1.pickle')
4444-
# This code was executed once on v0.14.1 to generate the pickle:
4445-
#
4446-
# cat = Categorical(labels=np.arange(3), levels=['a', 'b', 'c', 'd'],
4447-
# name='foobar')
4448-
# with open(pickle_path, 'wb') as f: pickle.dump(cat, f)
4449-
#
4450-
self.assert_categorical_equal(cat, pd.read_pickle(pickle_path))
4451-
4452-
def test_pickle_v0_15_2(self):
4453-
# ordered -> _ordered
4454-
# GH 9347
4455-
4456-
# we have the name warning
4457-
# 10482
4458-
with tm.assert_produces_warning(UserWarning):
4459-
cat = pd.Categorical(values=['a', 'b', 'c'],
4460-
categories=['a', 'b', 'c', 'd'],
4461-
name='foobar', ordered=False)
4462-
pickle_path = os.path.join(tm.get_data_path(),
4463-
'categorical_0_15_2.pickle')
4464-
# This code was executed once on v0.15.2 to generate the pickle:
4465-
#
4466-
# cat = Categorical(labels=np.arange(3), levels=['a', 'b', 'c', 'd'],
4467-
# name='foobar')
4468-
# with open(pickle_path, 'wb') as f: pickle.dump(cat, f)
4469-
#
4470-
self.assert_categorical_equal(cat, pd.read_pickle(pickle_path))
4471-
44724422
def test_concat_categorical(self):
44734423
# See GH 10177
44744424
df1 = pd.DataFrame(

setup.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ def pxd(name):
589589
'tests/data/legacy_msgpack/*/*.msgpack',
590590
'tests/data/*.csv*',
591591
'tests/data/*.dta',
592+
'tests/data/*.pickle',
592593
'tests/data/*.txt',
593594
'tests/data/*.xls',
594595
'tests/data/*.xlsx',
@@ -605,8 +606,7 @@ def pxd(name):
605606
'tests/data/html_encoding/*.html',
606607
'tests/json/data/*.json'],
607608
'pandas.tools': ['tests/data/*.csv'],
608-
'pandas.tests': ['data/*.pickle',
609-
'data/*.csv'],
609+
'pandas.tests': ['data/*.csv'],
610610
'pandas.tests.formats': ['data/*.csv'],
611611
'pandas.tests.indexes': ['data/*.pickle'],
612612
'pandas.tseries.tests': ['data/*.pickle',

0 commit comments

Comments
 (0)