Skip to content

Commit 3843471

Browse files
committed
Added _dict_compat to deal with datetime64-keyed dict
1 parent a25405a commit 3843471

File tree

4 files changed

+51
-25
lines changed

4 files changed

+51
-25
lines changed

pandas/core/common.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import pandas.lib as lib
2020
import pandas.tslib as tslib
2121
from pandas import compat
22-
from pandas.compat import StringIO, BytesIO, range, long, u, zip, map, string_types
22+
from pandas.compat import StringIO, BytesIO, range, long, u, zip, map, string_types, iteritems
2323

2424
from pandas.core.config import get_option
2525

@@ -3361,3 +3361,17 @@ def _random_state(state=None):
33613361
return np.random.RandomState()
33623362
else:
33633363
raise ValueError("random_state must be an integer, a numpy RandomState, or None")
3364+
3365+
def _dict_compat(d):
3366+
"""
3367+
Helper function to convert datetimelike-keyed dicts to Timestamp-keyed dict
3368+
3369+
Parameters
3370+
----------
3371+
d: dict like object
3372+
3373+
Returns
3374+
__________
3375+
dict
3376+
"""
3377+
return dict((_maybe_box_datetimelike(key), value) for key, value in iteritems(d))

pandas/core/frame.py

+3-9
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
_infer_dtype_from_scalar, _values_from_object,
2929
is_list_like, _maybe_box_datetimelike,
3030
is_categorical_dtype, is_object_dtype,
31-
_possibly_infer_to_datetimelike)
31+
_possibly_infer_to_datetimelike, _dict_compat)
3232
from pandas.core.generic import NDFrame, _shared_docs
3333
from pandas.core.index import Index, MultiIndex, _ensure_index
3434
from pandas.core.indexing import (maybe_droplevels,
@@ -5095,15 +5095,9 @@ def _homogenize(data, index, dtype=None):
50955095
v = v.reindex(index, copy=False)
50965096
else:
50975097
if isinstance(v, dict):
5098-
if lib.infer_dtype(v) in ['datetime64']:
5099-
v = {lib.Timestamp(key): v[key] for key in v}
5098+
v = _dict_compat(v)
51005099
oindex = index.astype('O')
5101-
if type(v) == dict:
5102-
# fast cython method
5103-
v = lib.fast_multiget(v, oindex.values, default=NA)
5104-
else:
5105-
v = lib.map_infer(oindex.values, v.get)
5106-
5100+
v = lib.fast_multiget(v, oindex.values, default=NA)
51075101
v = _sanitize_array(v, index, dtype=dtype, copy=False,
51085102
raise_cast_failure=False)
51095103

pandas/tests/test_common.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import sys
66

77
import nose
8-
from nose.tools import assert_equal
8+
from nose.tools import assert_equal, assert_dict_equal
99
import numpy as np
1010
from pandas.tslib import iNaT, NaT
1111
from pandas import Series, DataFrame, date_range, DatetimeIndex, Timestamp, Float64Index
@@ -1018,6 +1018,16 @@ def test_maybe_convert_string_to_array(self):
10181018
self.assertTrue(result.dtype == object)
10191019

10201020

1021+
def test_dict_compat():
1022+
data_datetime64 = {np.datetime64('1990-03-15'): 1,
1023+
np.datetime64('2015-03-15'): 2}
1024+
data_unchanged = {1: 2, 3: 4, 5: 6}
1025+
expected = {Timestamp('1990-3-15'): 1, Timestamp('2015-03-15'): 2}
1026+
assert_dict_equal(com._dict_compat(data_datetime64), expected)
1027+
assert_dict_equal(com._dict_compat(expected), expected)
1028+
assert_dict_equal(com._dict_compat(data_unchanged), data_unchanged)
1029+
1030+
10211031
if __name__ == '__main__':
10221032
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
10231033
exit=False)

pandas/tests/test_frame.py

+22-14
Original file line numberDiff line numberDiff line change
@@ -2955,20 +2955,28 @@ def test_constructor_dict_multiindex(self):
29552955
check(df, expected)
29562956

29572957
def test_constructor_dict_datetime64_index(self):
2958-
2959-
data = {1: {np.datetime64('1990-03-15'): 1},
2960-
2: {np.datetime64('1989-12-03'): 3},
2961-
3: {np.datetime64('1988-11-06'): 5},
2962-
4: {np.datetime64('1984-02-19'): 7}}
2963-
2964-
data_expected = {1: {Timestamp('1990-03-15'): 1},
2965-
2: {Timestamp('1989-12-03'): 3},
2966-
3: {Timestamp('1988-11-06'): 5},
2967-
4: {Timestamp('1984-02-19'): 7}}
2968-
2969-
result = DataFrame(data)
2970-
expected = DataFrame(data_expected)
2971-
assert_frame_equal(result, expected)
2958+
# GH 10160
2959+
dates_as_str = ['1984-02-19', '1988-11-06', '1989-12-03', '1990-03-15']
2960+
2961+
def create_data(constructor):
2962+
return dict((i, {constructor(s): 2*i}) for i, s in enumerate(dates_as_str))
2963+
2964+
data_datetime64 = create_data(np.datetime64)
2965+
data_datetime = create_data(lambda x: datetime.strptime(x, '%Y-%m-%d'))
2966+
data_Timestamp = create_data(Timestamp)
2967+
2968+
expected = DataFrame([{0: 0, 1: None, 2: None, 3: None},
2969+
{0: None, 1: 2, 2: None, 3: None},
2970+
{0: None, 1: None, 2: 4, 3: None},
2971+
{0: None, 1: None, 2: None, 3: 6}],
2972+
index=[Timestamp(dt) for dt in dates_as_str])
2973+
2974+
result_datetime64 = DataFrame(data_datetime64)
2975+
result_datetime = DataFrame(data_datetime)
2976+
result_Timestamp = DataFrame(data_Timestamp)
2977+
assert_frame_equal(result_datetime64, expected)
2978+
assert_frame_equal(result_datetime, expected)
2979+
assert_frame_equal(result_Timestamp, expected)
29722980

29732981

29742982
def _check_basic_constructor(self, empty):

0 commit comments

Comments
 (0)