Skip to content

Commit e6fd3db

Browse files
authored
BUG: Coerce to native types to_dict list and index (pandas-dev#46751) (pandas-dev#46752)
1 parent 1fde6d9 commit e6fd3db

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

doc/source/whatsnew/v1.5.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ Conversion
501501
- Bug in :func:`array` with ``FloatingDtype`` and values containing float-castable strings incorrectly raising (:issue:`45424`)
502502
- Bug when comparing string and datetime64ns objects causing ``OverflowError`` exception. (:issue:`45506`)
503503
- Bug in metaclass of generic abstract dtypes causing :meth:`DataFrame.apply` and :meth:`Series.apply` to raise for the built-in function ``type`` (:issue:`46684`)
504+
- Bug in :meth:`DataFrame.to_dict` for ``orient="list"`` or ``orient="index"`` was not returning native types (:issue:`46751`)
504505

505506
Strings
506507
^^^^^^^

pandas/core/frame.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1913,7 +1913,9 @@ def to_dict(self, orient: str = "dict", into=dict):
19131913
return into_c((k, v.to_dict(into)) for k, v in self.items())
19141914

19151915
elif orient == "list":
1916-
return into_c((k, v.tolist()) for k, v in self.items())
1916+
return into_c(
1917+
(k, list(map(maybe_box_native, v.tolist()))) for k, v in self.items()
1918+
)
19171919

19181920
elif orient == "split":
19191921
return into_c(
@@ -1964,7 +1966,7 @@ def to_dict(self, orient: str = "dict", into=dict):
19641966
if not self.index.is_unique:
19651967
raise ValueError("DataFrame index must be unique for orient='index'.")
19661968
return into_c(
1967-
(t[0], dict(zip(self.columns, t[1:])))
1969+
(t[0], dict(zip(self.columns, map(maybe_box_native, t[1:]))))
19681970
for t in self.itertuples(name=None)
19691971
)
19701972

pandas/tests/frame/methods/test_to_dict.py

+77
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,80 @@ def test_to_dict_orient_tight(self, index, columns):
344344
roundtrip = DataFrame.from_dict(df.to_dict(orient="tight"), orient="tight")
345345

346346
tm.assert_frame_equal(df, roundtrip)
347+
348+
@pytest.mark.parametrize(
349+
"orient",
350+
["dict", "list", "split", "records", "index", "tight"],
351+
)
352+
@pytest.mark.parametrize(
353+
"data,expected_types",
354+
(
355+
(
356+
{
357+
"a": [np.int64(1), 1, np.int64(3)],
358+
"b": [np.float64(1.0), 2.0, np.float64(3.0)],
359+
"c": [np.float64(1.0), 2, np.int64(3)],
360+
"d": [np.float64(1.0), "a", np.int64(3)],
361+
"e": [np.float64(1.0), ["a"], np.int64(3)],
362+
"f": [np.float64(1.0), ("a",), np.int64(3)],
363+
},
364+
{
365+
"a": [int, int, int],
366+
"b": [float, float, float],
367+
"c": [float, float, float],
368+
"d": [float, str, int],
369+
"e": [float, list, int],
370+
"f": [float, tuple, int],
371+
},
372+
),
373+
(
374+
{
375+
"a": [1, 2, 3],
376+
"b": [1.1, 2.2, 3.3],
377+
},
378+
{
379+
"a": [int, int, int],
380+
"b": [float, float, float],
381+
},
382+
),
383+
),
384+
)
385+
def test_to_dict_returns_native_types(self, orient, data, expected_types):
386+
# GH 46751
387+
# Tests we get back native types for all orient types
388+
df = DataFrame(data)
389+
result = df.to_dict(orient)
390+
if orient == "dict":
391+
assertion_iterator = (
392+
(i, key, value)
393+
for key, index_value_map in result.items()
394+
for i, value in index_value_map.items()
395+
)
396+
elif orient == "list":
397+
assertion_iterator = (
398+
(i, key, value)
399+
for key, values in result.items()
400+
for i, value in enumerate(values)
401+
)
402+
elif orient in {"split", "tight"}:
403+
assertion_iterator = (
404+
(i, key, result["data"][i][j])
405+
for i in result["index"]
406+
for j, key in enumerate(result["columns"])
407+
)
408+
elif orient == "records":
409+
assertion_iterator = (
410+
(i, key, value)
411+
for i, record in enumerate(result)
412+
for key, value in record.items()
413+
)
414+
elif orient == "index":
415+
assertion_iterator = (
416+
(i, key, value)
417+
for i, record in result.items()
418+
for key, value in record.items()
419+
)
420+
421+
for i, key, value in assertion_iterator:
422+
assert value == data[key][i]
423+
assert type(value) is expected_types[key][i]

0 commit comments

Comments
 (0)