Skip to content

Commit 89b4e5b

Browse files
ethanluoycjreback
authored andcommitted
BUG: Fix to_dict() problem when using only datetime #11247
Fix a bug where to_dict() does not return Timestamp when there is only datetime dtype present.
1 parent bd2248c commit 89b4e5b

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

doc/source/whatsnew/v0.17.1.txt

+1
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,4 @@ Bug Fixes
9696
- Bugs in ``to_excel`` with duplicate columns (:issue:`11007`, :issue:`10982`, :issue:`10970`)
9797
- Fixed a bug that prevented the construction of an empty series of dtype
9898
``datetime64[ns, tz]`` (:issue:`11245`).
99+
- Bug in ``DataFrame.to_dict()`` produces a ``np.datetime64`` object instead of ``Timestamp`` when only datetime is present in data (:issue:`11327`)

pandas/core/frame.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -802,11 +802,12 @@ def to_dict(self, orient='dict'):
802802
elif orient.lower().startswith('sp'):
803803
return {'index': self.index.tolist(),
804804
'columns': self.columns.tolist(),
805-
'data': self.values.tolist()}
805+
'data': lib.map_infer(self.values.ravel(), _maybe_box_datetimelike)
806+
.reshape(self.values.shape).tolist()}
806807
elif orient.lower().startswith('s'):
807-
return dict((k, v) for k, v in compat.iteritems(self))
808+
return dict((k, _maybe_box_datetimelike(v)) for k, v in compat.iteritems(self))
808809
elif orient.lower().startswith('r'):
809-
return [dict((k, v) for k, v in zip(self.columns, row))
810+
return [dict((k, _maybe_box_datetimelike(v)) for k, v in zip(self.columns, row))
810811
for row in self.values]
811812
elif orient.lower().startswith('i'):
812813
return dict((k, v.to_dict()) for k, v in self.iterrows())

pandas/tests/test_frame.py

+52
Original file line numberDiff line numberDiff line change
@@ -4728,6 +4728,58 @@ def test_to_dict(self):
47284728
for k2, v2 in compat.iteritems(v):
47294729
self.assertEqual(v2, recons_data[k2][k])
47304730

4731+
def test_to_dict_timestamp(self):
4732+
4733+
# GH11247
4734+
# split/records producing np.datetime64 rather than Timestamps
4735+
# on datetime64[ns] dtypes only
4736+
4737+
tsmp = Timestamp('20130101')
4738+
test_data = DataFrame({'A': [tsmp, tsmp], 'B': [tsmp, tsmp]})
4739+
test_data_mixed = DataFrame({'A': [tsmp, tsmp], 'B': [1, 2]})
4740+
4741+
expected_records = [{'A': tsmp, 'B': tsmp},
4742+
{'A': tsmp, 'B': tsmp}]
4743+
expected_records_mixed = [{'A': tsmp, 'B': 1},
4744+
{'A': tsmp, 'B': 2}]
4745+
4746+
tm.assert_almost_equal(test_data.to_dict(
4747+
orient='records'), expected_records)
4748+
tm.assert_almost_equal(test_data_mixed.to_dict(
4749+
orient='records'), expected_records_mixed)
4750+
4751+
expected_series = {
4752+
'A': Series([tsmp, tsmp]),
4753+
'B': Series([tsmp, tsmp]),
4754+
}
4755+
expected_series_mixed = {
4756+
'A': Series([tsmp, tsmp]),
4757+
'B': Series([1, 2]),
4758+
}
4759+
4760+
tm.assert_almost_equal(test_data.to_dict(
4761+
orient='series'), expected_series)
4762+
tm.assert_almost_equal(test_data_mixed.to_dict(
4763+
orient='series'), expected_series_mixed)
4764+
4765+
expected_split = {
4766+
'index': [0, 1],
4767+
'data': [[tsmp, tsmp],
4768+
[tsmp, tsmp]],
4769+
'columns': ['A', 'B']
4770+
}
4771+
expected_split_mixed = {
4772+
'index': [0, 1],
4773+
'data': [[tsmp, 1],
4774+
[tsmp, 2]],
4775+
'columns': ['A', 'B']
4776+
}
4777+
4778+
tm.assert_almost_equal(test_data.to_dict(
4779+
orient='split'), expected_split)
4780+
tm.assert_almost_equal(test_data_mixed.to_dict(
4781+
orient='split'), expected_split_mixed)
4782+
47314783
def test_to_dict_invalid_orient(self):
47324784
df = DataFrame({'A':[0, 1]})
47334785
self.assertRaises(ValueError, df.to_dict, orient='xinvalid')

0 commit comments

Comments
 (0)