Skip to content

Commit e6abfcf

Browse files
committed
ENH: add a metaclass to CategoricalDtype to provide issubclass support (for select_dtypes)
1 parent 7788f46 commit e6abfcf

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

pandas/core/common.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,23 @@ class to receive bound method
106106
else:
107107
setattr(cls, name, func)
108108

109+
class CategoricalDtypeType(type):
110+
"""
111+
the type of CategoricalDtype, this metaclass determines subclass ability
112+
"""
113+
def __init__(cls, name, bases, attrs):
114+
pass
115+
109116
class CategoricalDtype(object):
117+
__meta__ = CategoricalDtypeType
110118
"""
111119
A np.dtype duck-typed class, suitable for holding a custom categorical dtype.
112120
113121
THIS IS NOT A REAL NUMPY DTYPE, but essentially a sub-class of np.object
114122
"""
115123
name = 'category'
116124
names = None
117-
type = np.object_
125+
type = CategoricalDtypeType
118126
subdtype = None
119127
kind = 'O'
120128
str = '|O08'
@@ -1702,6 +1710,8 @@ def _get_dtype_from_object(dtype):
17021710
elif isinstance(dtype, compat.string_types):
17031711
if dtype == 'datetime' or dtype == 'timedelta':
17041712
dtype += '64'
1713+
elif dtype == 'category':
1714+
return CategoricalDtypeType
17051715
try:
17061716
return _get_dtype_from_object(getattr(np, dtype))
17071717
except AttributeError:
@@ -1712,10 +1722,6 @@ def _get_dtype_from_object(dtype):
17121722
return _get_dtype_from_object(np.dtype(dtype))
17131723

17141724

1715-
_string_dtypes = frozenset(map(_get_dtype_from_object, (compat.binary_type,
1716-
compat.text_type)))
1717-
1718-
17191725
def _get_info_slice(obj, indexer):
17201726
"""Slice the info axis of `obj` with `indexer`."""
17211727
if not hasattr(obj, '_info_axis_number'):
@@ -2383,6 +2389,7 @@ def is_bool_dtype(arr_or_dtype):
23832389
def is_categorical_dtype(arr_or_dtype):
23842390
if hasattr(arr_or_dtype,'dtype'):
23852391
arr_or_dtype = arr_or_dtype.dtype
2392+
23862393
if isinstance(arr_or_dtype, CategoricalDtype):
23872394
return True
23882395
try:
@@ -2427,6 +2434,10 @@ def _is_sequence(x):
24272434
return False
24282435

24292436

2437+
_string_dtypes = frozenset(map(_get_dtype_from_object, (compat.binary_type,
2438+
compat.text_type)))
2439+
2440+
24302441
_ensure_float64 = algos.ensure_float64
24312442
_ensure_float32 = algos.ensure_float32
24322443
_ensure_int64 = algos.ensure_int64

pandas/tests/test_frame.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -13020,11 +13020,16 @@ def test_select_dtypes_include(self):
1302013020
'b': list(range(1, 4)),
1302113021
'c': np.arange(3, 6).astype('u1'),
1302213022
'd': np.arange(4.0, 7.0, dtype='float64'),
13023-
'e': [True, False, True]})
13023+
'e': [True, False, True],
13024+
'f': pd.Categorical(list('abc'))})
1302413025
ri = df.select_dtypes(include=[np.number])
1302513026
ei = df[['b', 'c', 'd']]
1302613027
tm.assert_frame_equal(ri, ei)
1302713028

13029+
ri = df.select_dtypes(include=[np.number,'category'])
13030+
ei = df[['b', 'c', 'd', 'f']]
13031+
tm.assert_frame_equal(ri, ei)
13032+
1302813033
def test_select_dtypes_exclude(self):
1302913034
df = DataFrame({'a': list('abc'),
1303013035
'b': list(range(1, 4)),

0 commit comments

Comments
 (0)