From 409906e627f6e91ba598f72297f9af5724ec6133 Mon Sep 17 00:00:00 2001 From: jreback Date: Tue, 21 Jan 2014 13:40:40 -0500 Subject: [PATCH] BUG: Bug in Series construction of mixed type with datelike and an integer (which should result in object type and not automatic conversion) --- doc/source/release.rst | 2 ++ pandas/tests/test_indexing.py | 6 ++++++ pandas/tests/test_series.py | 5 +++++ pandas/tslib.pyx | 13 ++++++++++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index 6b167a8939bb5..a3792ae74b023 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -130,6 +130,8 @@ Bug Fixes and off-diagonal plots, see (:issue:`5497`). - Regression in Series with a multi-index via ix (:issue:`6018`) - Bug in Series.xs with a multi-index (:issue:`6018`) + - Bug in Series construction of mixed type with datelike and an integer (which should result in + object type and not automatic conversion) (:issue:`6028`) pandas 0.13.0 ------------- diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index 7c01f5f700c2b..4e60037017645 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -623,6 +623,12 @@ def test_loc_general(self): self.assert_((result.columns == ['A','B']).all() == True) self.assert_((result.index == ['A','B']).all() == True) + # mixed type + result = DataFrame({ 'a' : [Timestamp('20130101')], 'b' : [1] }).iloc[0] + expected = Series([ Timestamp('20130101'), 1],index=['a','b']) + assert_series_equal(result,expected) + self.assert_(result.dtype == object) + def test_loc_setitem_frame(self): df = self.frame_labels diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index f3f3127bbe875..6df7028092a7a 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -573,6 +573,11 @@ def test_constructor_dtype_datetime64(self): result = Series([datetime(3000,1,1)]) self.assert_(result[0] == datetime(3000,1,1,0,0)) + # don't mix types + result = Series([ Timestamp('20130101'), 1],index=['a','b']) + self.assert_(result['a'] == Timestamp('20130101')) + self.assert_(result['b'] == 1) + def test_constructor_dict(self): d = {'a': 0., 'b': 1., 'c': 2.} result = Series(d, index=['b', 'c', 'd', 'a']) diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index c2a727d7d3394..ccf7174c7ae05 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -1005,7 +1005,7 @@ def array_to_datetime(ndarray[object] values, raise_=False, dayfirst=False, ndarray[int64_t] iresult ndarray[object] oresult pandas_datetimestruct dts - bint utc_convert = bool(utc) + bint utc_convert = bool(utc), seen_integer=0, seen_datetime=0 _TSObject _ts int64_t m = cast_from_unit(None,unit) @@ -1017,6 +1017,7 @@ def array_to_datetime(ndarray[object] values, raise_=False, dayfirst=False, if _checknull_with_nat(val): iresult[i] = iNaT elif PyDateTime_Check(val): + seen_datetime=1 if val.tzinfo is not None: if utc_convert: _ts = convert_to_tsobject(val, None, unit) @@ -1047,6 +1048,7 @@ def array_to_datetime(ndarray[object] values, raise_=False, dayfirst=False, iresult[i] = _date_to_datetime64(val, &dts) try: _check_dts_bounds(&dts) + seen_datetime=1 except ValueError: if coerce: iresult[i] = iNaT @@ -1058,6 +1060,7 @@ def array_to_datetime(ndarray[object] values, raise_=False, dayfirst=False, else: try: iresult[i] = _get_datetime64_nanos(val) + seen_datetime=1 except ValueError: if coerce: iresult[i] = iNaT @@ -1070,11 +1073,13 @@ def array_to_datetime(ndarray[object] values, raise_=False, dayfirst=False, iresult[i] = iNaT else: iresult[i] = val*m + seen_integer=1 elif util.is_float_object(val) and not coerce: if val != val or val == iNaT: iresult[i] = iNaT else: iresult[i] = cast_from_unit(val,unit) + seen_integer=1 else: try: if len(val) == 0: @@ -1114,6 +1119,12 @@ def array_to_datetime(ndarray[object] values, raise_=False, dayfirst=False, continue raise + # don't allow mixed integers and datetime like + # higher levels can catch and coerce to object, for + # example + if seen_integer and seen_datetime: + raise ValueError("mixed datetimes and integers in passed array") + return result except OutOfBoundsDatetime: if raise_: