Skip to content

Commit 1e51c27

Browse files
committed
Merge pull request #5192 from jreback/compound_dtypes
BUG: raise NotImplementedError on passing of compound dtypes in constructors (GH5191)
2 parents 282bf26 + 1398ad6 commit 1e51c27

File tree

7 files changed

+49
-7
lines changed

7 files changed

+49
-7
lines changed

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ Bug Fixes
590590
- Fixed segfault on ``isnull(MultiIndex)`` (now raises an error instead)
591591
(:issue:`5123`, :issue:`5125`)
592592
- Allow duplicate indices when performing operations that align (:issue:`5185`)
593+
- Compound dtypes in a constructor raise ``NotImplementedError`` (:issue:`5191`)
593594

594595
pandas 0.12.0
595596
-------------

pandas/core/frame.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ def __init__(self, data=None, index=None, columns=None, dtype=None,
189189
copy=False):
190190
if data is None:
191191
data = {}
192+
if dtype is not None:
193+
dtype = self._validate_dtype(dtype)
192194

193195
if isinstance(data, DataFrame):
194196
data = data._data
@@ -276,9 +278,6 @@ def _init_dict(self, data, index, columns, dtype=None):
276278
Segregate Series based on type and coerce into matrices.
277279
Needs to handle a lot of exceptional cases.
278280
"""
279-
if dtype is not None:
280-
dtype = np.dtype(dtype)
281-
282281
if columns is not None:
283282
columns = _ensure_index(columns)
284283

@@ -4659,9 +4658,6 @@ def _get_names_from_index(data):
46594658
def _homogenize(data, index, dtype=None):
46604659
from pandas.core.series import _sanitize_array
46614660

4662-
if dtype is not None:
4663-
dtype = np.dtype(dtype)
4664-
46654661
oindex = None
46664662
homogenized = []
46674663

pandas/core/generic.py

+12
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ def __init__(self, data, axes=None, copy=False, dtype=None, fastpath=False):
8989
object.__setattr__(self, '_data', data)
9090
object.__setattr__(self, '_item_cache', {})
9191

92+
def _validate_dtype(self, dtype):
93+
""" validate the passed dtype """
94+
95+
if dtype is not None:
96+
dtype = np.dtype(dtype)
97+
98+
# a compound dtype
99+
if dtype.kind == 'V':
100+
raise NotImplementedError("compound dtypes are not implemented"
101+
"in the {0} constructor".format(self.__class__.__name__))
102+
return dtype
103+
92104
def _init_mgr(self, mgr, axes=None, dtype=None, copy=False):
93105
""" passed a manager and a axes dict """
94106
for a, axe in axes.items():

pandas/core/panel.py

+2
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ def _init_data(self, data, copy, dtype, **kwargs):
140140
"""
141141
if data is None:
142142
data = {}
143+
if dtype is not None:
144+
dtype = self._validate_dtype(dtype)
143145

144146
passed_axes = [kwargs.get(a) for a in self._AXIS_ORDERS]
145147
axes = None

pandas/core/series.py

+2
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ def __init__(self, data=None, index=None, dtype=None, name=None,
139139

140140
if data is None:
141141
data = {}
142+
if dtype is not None:
143+
dtype = self._validate_dtype(dtype)
142144

143145
if isinstance(data, MultiIndex):
144146
raise NotImplementedError

pandas/tests/test_frame.py

+15
Original file line numberDiff line numberDiff line change
@@ -10709,6 +10709,21 @@ def test_constructor_series_copy(self):
1070910709

1071010710
self.assert_(not (series['A'] == 5).all())
1071110711

10712+
def test_constructor_compound_dtypes(self):
10713+
# GH 5191
10714+
# compound dtypes should raise not-implementederror
10715+
10716+
def f(dtype):
10717+
return DataFrame(data = list(itertools.repeat((datetime(2001, 1, 1), "aa", 20), 9)),
10718+
columns=["A", "B", "C"], dtype=dtype)
10719+
10720+
self.assertRaises(NotImplementedError, f, [("A","datetime64[h]"), ("B","str"), ("C","int32")])
10721+
10722+
# these work (though results may be unexpected)
10723+
f('int64')
10724+
f('float64')
10725+
f('M8[ns]')
10726+
1071210727
def test_assign_columns(self):
1071310728
self.frame['hi'] = 'there'
1071410729

pandas/tests/test_generic.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def _construct(self, shape, value=None, dtype=None, **kwargs):
8686
arr = np.repeat(arr,new_shape).reshape(shape)
8787
else:
8888
arr = np.random.randn(*shape)
89-
return self._typ(arr,**kwargs)
89+
return self._typ(arr,dtype=dtype,**kwargs)
9090

9191
def _compare(self, result, expected):
9292
self._comparator(result,expected)
@@ -210,6 +210,20 @@ def test_downcast(self):
210210
expected = o.astype(np.int64)
211211
self._compare(result, expected)
212212

213+
def test_constructor_compound_dtypes(self):
214+
# GH 5191
215+
# compound dtypes should raise not-implementederror
216+
217+
def f(dtype):
218+
return self._construct(shape=3, dtype=dtype)
219+
220+
self.assertRaises(NotImplementedError, f, [("A","datetime64[h]"), ("B","str"), ("C","int32")])
221+
222+
# these work (though results may be unexpected)
223+
f('int64')
224+
f('float64')
225+
f('M8[ns]')
226+
213227
class TestSeries(unittest.TestCase, Generic):
214228
_typ = Series
215229
_comparator = lambda self, x, y: assert_series_equal(x,y)

0 commit comments

Comments
 (0)