Skip to content

Commit 02142d3

Browse files
reidy-pkornilova203
authored andcommitted
API: Preserve int columns in to_dict('index') (pandas-dev#20444)
1 parent f2c1acc commit 02142d3

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

doc/source/whatsnew/v0.23.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ Other API Changes
716716
- :func:`Series.str.replace` now takes an optional `regex` keyword which, when set to ``False``, uses literal string replacement rather than regex replacement (:issue:`16808`)
717717
- :func:`DatetimeIndex.strftime` and :func:`PeriodIndex.strftime` now return an ``Index`` instead of a numpy array to be consistent with similar accessors (:issue:`20127`)
718718
- Constructing a Series from a list of length 1 no longer broadcasts this list when a longer index is specified (:issue:`19714`, :issue:`20391`).
719+
- :func:`DataFrame.to_dict` with ``orient='index'`` no longer casts int columns to float for a DataFrame with only int and float columns (:issue:`18580`)
719720

720721
.. _whatsnew_0230.deprecations:
721722

pandas/core/frame.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,8 @@ def to_dict(self, orient='dict', into=dict):
11021102
for k, v in zip(self.columns, np.atleast_1d(row)))
11031103
for row in self.values]
11041104
elif orient.lower().startswith('i'):
1105-
return into_c((k, v.to_dict(into)) for k, v in self.iterrows())
1105+
return into_c((t[0], dict(zip(self.columns, t[1:])))
1106+
for t in self.itertuples())
11061107
else:
11071108
raise ValueError("orient '%s' not understood" % orient)
11081109

pandas/tests/frame/test_convert_to.py

+27
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pytest
66
import pytz
77
import collections
8+
from collections import OrderedDict, defaultdict
89
import numpy as np
910

1011
from pandas import compat
@@ -288,3 +289,29 @@ def test_frame_to_dict_tz(self):
288289
]
289290
tm.assert_dict_equal(result[0], expected[0])
290291
tm.assert_dict_equal(result[1], expected[1])
292+
293+
@pytest.mark.parametrize('into, expected', [
294+
(dict, {0: {'int_col': 1, 'float_col': 1.0},
295+
1: {'int_col': 2, 'float_col': 2.0},
296+
2: {'int_col': 3, 'float_col': 3.0}}),
297+
(OrderedDict, OrderedDict([(0, {'int_col': 1, 'float_col': 1.0}),
298+
(1, {'int_col': 2, 'float_col': 2.0}),
299+
(2, {'int_col': 3, 'float_col': 3.0})])),
300+
(defaultdict(list), defaultdict(list,
301+
{0: {'int_col': 1, 'float_col': 1.0},
302+
1: {'int_col': 2, 'float_col': 2.0},
303+
2: {'int_col': 3, 'float_col': 3.0}}))
304+
])
305+
def test_to_dict_index_dtypes(self, into, expected):
306+
# GH 18580
307+
# When using to_dict(orient='index') on a dataframe with int
308+
# and float columns only the int columns were cast to float
309+
310+
df = DataFrame({'int_col': [1, 2, 3],
311+
'float_col': [1.0, 2.0, 3.0]})
312+
313+
result = df.to_dict(orient='index', into=into)
314+
cols = ['int_col', 'float_col']
315+
result = DataFrame.from_dict(result, orient='index')[cols]
316+
expected = DataFrame.from_dict(expected, orient='index')[cols]
317+
tm.assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)